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

1591 lines
43 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: snapdata.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "preDNSsn.h"
  11. #include <SnapBase.h>
  12. #include "resource.h"
  13. #include "DNSSnap.h"
  14. #include "dnsutil.h"
  15. #include "snapdata.h"
  16. #include "server.h"
  17. #include "servwiz.h"
  18. #include <prsht.h>
  19. #include <svcguid.h>
  20. #ifdef DEBUG_ALLOCATOR
  21. #ifdef _DEBUG
  22. #define new DEBUG_NEW
  23. #undef THIS_FILE
  24. static char THIS_FILE[] = __FILE__;
  25. #endif
  26. #endif
  27. ///////////////////////////////////////////////////////////////////////////////
  28. // GLOBAL FUNCTIONS
  29. HRESULT SaveStringHelper(LPCWSTR pwsz, IStream* pStm)
  30. {
  31. ASSERT(pStm);
  32. ULONG nBytesWritten;
  33. HRESULT hr;
  34. DWORD nLen = static_cast<DWORD>(wcslen(pwsz)+1); // WCHAR including NULL
  35. hr = pStm->Write((void*)&nLen, sizeof(DWORD),&nBytesWritten);
  36. ASSERT(nBytesWritten == sizeof(DWORD));
  37. if (FAILED(hr))
  38. return hr;
  39. hr = pStm->Write((void*)pwsz, sizeof(WCHAR)*nLen,&nBytesWritten);
  40. ASSERT(nBytesWritten == sizeof(WCHAR)*nLen);
  41. TRACE(_T("SaveStringHelper(<%s> nLen = %d\n"),pwsz,nLen);
  42. return hr;
  43. }
  44. HRESULT LoadStringHelper(CString& sz, IStream* pStm)
  45. {
  46. ASSERT(pStm);
  47. HRESULT hr;
  48. ULONG nBytesRead;
  49. DWORD nLen = 0;
  50. hr = pStm->Read((void*)&nLen,sizeof(DWORD), &nBytesRead);
  51. ASSERT(nBytesRead == sizeof(DWORD));
  52. if (FAILED(hr) || (nBytesRead != sizeof(DWORD)))
  53. return hr;
  54. hr = pStm->Read((void*)sz.GetBuffer(nLen),sizeof(WCHAR)*nLen, &nBytesRead);
  55. ASSERT(nBytesRead == sizeof(WCHAR)*nLen);
  56. sz.ReleaseBuffer();
  57. TRACE(_T("LoadStringHelper(<%s> nLen = %d\n"),(LPCTSTR)sz,nLen);
  58. return hr;
  59. }
  60. HRESULT SaveDWordHelper(IStream* pStm, DWORD dw)
  61. {
  62. ULONG nBytesWritten;
  63. HRESULT hr = pStm->Write((void*)&dw, sizeof(DWORD),&nBytesWritten);
  64. if (nBytesWritten < sizeof(DWORD))
  65. hr = STG_E_CANTSAVE;
  66. return hr;
  67. }
  68. HRESULT LoadDWordHelper(IStream* pStm, DWORD* pdw)
  69. {
  70. ULONG nBytesRead;
  71. HRESULT hr = pStm->Read((void*)pdw,sizeof(DWORD), &nBytesRead);
  72. ASSERT(nBytesRead == sizeof(DWORD));
  73. return hr;
  74. }
  75. //////////////////////////////////////////////////////////////////////
  76. // CDNSQueryFilterPageBase
  77. class CDNSQueryFilterSheet; // fwd decl
  78. class CDNSQueryFilterPageBase : public CPropertyPage
  79. {
  80. public:
  81. CDNSQueryFilterPageBase(UINT nIDD, CDNSQueryFilterSheet* pSheet)
  82. : CPropertyPage(nIDD)
  83. {
  84. m_pSheet = pSheet;
  85. m_bDirty = FALSE;
  86. m_bInit = FALSE;
  87. }
  88. protected:
  89. CDNSQueryFilterSheet* m_pSheet;
  90. void SetDirty();
  91. void Init();
  92. BOOL IsDirty() { return m_bDirty;}
  93. virtual BOOL OnInitDialog();
  94. afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
  95. afx_msg void OnWhatsThis();
  96. afx_msg BOOL OnHelp(WPARAM wParam, LPARAM lParam);
  97. private:
  98. BOOL m_bInit;
  99. BOOL m_bDirty;
  100. HWND m_hWndWhatsThis; // hwnd of right click "What's this" help
  101. DECLARE_MESSAGE_MAP()
  102. };
  103. //////////////////////////////////////////////////////////////////////
  104. // CDNSQueryFilterNamePage
  105. class CDNSQueryFilterNamePage : public CDNSQueryFilterPageBase
  106. {
  107. public:
  108. CDNSQueryFilterNamePage(CDNSQueryFilterSheet* pSheet)
  109. : CDNSQueryFilterPageBase(IDD_FILTERING_NAME, pSheet)
  110. {
  111. }
  112. protected:
  113. virtual BOOL OnInitDialog();
  114. virtual BOOL OnApply();
  115. afx_msg void OnRadioClicked();
  116. afx_msg void OnEditChange();
  117. private:
  118. CEdit* GetStartsStringEdit() { return (CEdit*)GetDlgItem(IDC_EDIT_FILTER_STARTS);}
  119. CEdit* GetContainsStringEdit() { return (CEdit*)GetDlgItem(IDC_EDIT_FILTER_CONTAINS);}
  120. CEdit* GetRangeFromStringEdit() { return (CEdit*)GetDlgItem(IDC_EDIT_FILTER_RANGE_FROM);}
  121. CEdit* GetRangeToStringEdit() { return (CEdit*)GetDlgItem(IDC_EDIT_FILTER_RANGE_TO);}
  122. CButton* GetRadioNone() { return (CButton*)GetDlgItem(IDC_RADIO_FILTER_NONE);}
  123. CButton* GetRadioStarts() { return (CButton*)GetDlgItem(IDC_RADIO_FILTER_STARTS);}
  124. CButton* GetRadioContains() { return (CButton*)GetDlgItem(IDC_RADIO_FILTER_CONTAINS);}
  125. CButton* GetRadioRange() { return (CButton*)GetDlgItem(IDC_RADIO_FILTER_RANGE);}
  126. // utility methods
  127. UINT GetSelectedRadioButtonID();
  128. void SyncControls(UINT nRadioID);
  129. void GetEditText(UINT nID, CString& s);
  130. DECLARE_MESSAGE_MAP()
  131. };
  132. //////////////////////////////////////////////////////////////////////
  133. // CDNSQueryFilterAdvancedPage
  134. class CDNSQueryFilterAdvancedPage : public CDNSQueryFilterPageBase
  135. {
  136. public:
  137. CDNSQueryFilterAdvancedPage(CDNSQueryFilterSheet* pSheet)
  138. : CDNSQueryFilterPageBase(IDD_FILTERING_LIMITS, pSheet)
  139. {
  140. }
  141. protected:
  142. virtual BOOL OnInitDialog();
  143. virtual BOOL OnApply();
  144. afx_msg void OnCountEditChange();
  145. CDNSUnsignedIntEdit m_maxCountEdit;
  146. DECLARE_MESSAGE_MAP()
  147. };
  148. //////////////////////////////////////////////////////////////////////
  149. // CDNSQueryFilterSheet
  150. class CDNSQueryFilterSheet : public CPropertySheet
  151. {
  152. public:
  153. CDNSQueryFilterSheet(CDNSQueryFilter* pQueryFilter, CComponentDataObject* pComponentData)
  154. : CPropertySheet(IDS_SNAPIN_FILTERING_TITLE),
  155. m_namePage(this), m_advancedPage(this), m_pComponentData(pComponentData)
  156. {
  157. m_psh.dwFlags |= PSH_NOAPPLYNOW;
  158. m_pQueryFilter = pQueryFilter;
  159. AddPage(&m_namePage);
  160. AddPage(&m_advancedPage);
  161. m_bInit = FALSE;
  162. }
  163. CDNSQueryFilter* GetQueryFilter() { return m_pQueryFilter;}
  164. CComponentDataObject* GetComponentData() { return m_pComponentData; }
  165. void SetSheetStyle()
  166. {
  167. DWORD dwStyle = ::GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE);
  168. dwStyle |= WS_EX_CONTEXTHELP; // force the [?] button
  169. ::SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE, dwStyle);
  170. }
  171. private:
  172. void Init()
  173. {
  174. if (m_bInit)
  175. return;
  176. m_bInit = TRUE;
  177. CWnd* p = GetDlgItem(IDOK);
  178. if (p)
  179. p->EnableWindow(FALSE);
  180. }
  181. void SetDirty()
  182. {
  183. if (!m_bInit)
  184. return;
  185. GetDlgItem(IDOK)->EnableWindow(TRUE);
  186. }
  187. BOOL m_bInit;
  188. CComponentDataObject* m_pComponentData;
  189. CDNSQueryFilter* m_pQueryFilter;
  190. CDNSQueryFilterNamePage m_namePage;
  191. CDNSQueryFilterAdvancedPage m_advancedPage;
  192. friend class CDNSQueryFilterPageBase;
  193. friend class CDNSQueryFilterNamePage;
  194. friend class CDNSQueryFilterAdvancedPage;
  195. };
  196. //////////////////////////////////////////////////////////////////////
  197. // CDNSQueryFilterPageBase IMPLEMENTATION
  198. BOOL CDNSQueryFilterPageBase::OnInitDialog()
  199. {
  200. BOOL bRet = CPropertyPage::OnInitDialog();
  201. m_pSheet->SetSheetStyle();
  202. return bRet;
  203. }
  204. void CDNSQueryFilterPageBase::SetDirty()
  205. {
  206. if (!m_bInit)
  207. return;
  208. m_bDirty = TRUE;
  209. m_pSheet->SetDirty();
  210. }
  211. void CDNSQueryFilterPageBase::Init()
  212. {
  213. m_bInit = TRUE;
  214. m_pSheet->Init();
  215. }
  216. BEGIN_MESSAGE_MAP(CDNSQueryFilterPageBase, CPropertyPage)
  217. ON_WM_CONTEXTMENU()
  218. ON_MESSAGE(WM_HELP, OnHelp)
  219. ON_COMMAND(IDM_WHATS_THIS, OnWhatsThis)
  220. END_MESSAGE_MAP()
  221. void CDNSQueryFilterPageBase::OnWhatsThis()
  222. {
  223. //
  224. // Display context help for a control
  225. //
  226. if ( m_hWndWhatsThis )
  227. {
  228. //
  229. // Build our own HELPINFO struct to pass to the underlying
  230. // CS help functions built into the framework
  231. //
  232. int iCtrlID = ::GetDlgCtrlID(m_hWndWhatsThis);
  233. HELPINFO helpInfo;
  234. ZeroMemory(&helpInfo, sizeof(HELPINFO));
  235. helpInfo.cbSize = sizeof(HELPINFO);
  236. helpInfo.hItemHandle = m_hWndWhatsThis;
  237. helpInfo.iCtrlId = iCtrlID;
  238. m_pSheet->GetComponentData()->OnDialogContextHelp(m_nIDHelp, &helpInfo);
  239. }
  240. }
  241. BOOL CDNSQueryFilterPageBase::OnHelp(WPARAM /*wParam*/, LPARAM lParam)
  242. {
  243. const LPHELPINFO pHelpInfo = (LPHELPINFO)lParam;
  244. if (pHelpInfo && pHelpInfo->iContextType == HELPINFO_WINDOW)
  245. {
  246. //
  247. // Display context help for a control
  248. //
  249. m_pSheet->GetComponentData()->OnDialogContextHelp(m_nIDHelp, pHelpInfo);
  250. }
  251. return TRUE;
  252. }
  253. void CDNSQueryFilterPageBase::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
  254. {
  255. //
  256. // point is in screen coordinates
  257. //
  258. CMenu bar;
  259. if ( bar.LoadMenu(IDR_WHATS_THIS_CONTEXT_MENU1) )
  260. {
  261. CMenu& popup = *bar.GetSubMenu (0);
  262. ASSERT(popup.m_hMenu);
  263. if ( popup.TrackPopupMenu (TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
  264. point.x, // in screen coordinates
  265. point.y, // in screen coordinates
  266. this) ) // route commands through main window
  267. {
  268. m_hWndWhatsThis = 0;
  269. ScreenToClient (&point);
  270. CWnd* pChild = ChildWindowFromPoint (point, // in client coordinates
  271. CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
  272. if ( pChild )
  273. {
  274. m_hWndWhatsThis = pChild->m_hWnd;
  275. }
  276. }
  277. }
  278. }
  279. //////////////////////////////////////////////////////////////////////
  280. // CDNSQueryFilterNamePage IMPLEMENTATION
  281. BEGIN_MESSAGE_MAP(CDNSQueryFilterNamePage, CDNSQueryFilterPageBase)
  282. ON_BN_CLICKED(IDC_RADIO_FILTER_NONE, OnRadioClicked)
  283. ON_BN_CLICKED(IDC_RADIO_FILTER_STARTS, OnRadioClicked)
  284. ON_BN_CLICKED(IDC_RADIO_FILTER_CONTAINS, OnRadioClicked)
  285. ON_BN_CLICKED(IDC_RADIO_FILTER_RANGE, OnRadioClicked)
  286. ON_EN_CHANGE(IDC_EDIT_FILTER_STARTS, OnEditChange)
  287. ON_EN_CHANGE(IDC_EDIT_FILTER_CONTAINS, OnEditChange)
  288. ON_EN_CHANGE(IDC_EDIT_FILTER_RANGE_FROM, OnEditChange)
  289. ON_EN_CHANGE(IDC_EDIT_FILTER_RANGE_TO, OnEditChange)
  290. END_MESSAGE_MAP()
  291. UINT CDNSQueryFilterNamePage::GetSelectedRadioButtonID()
  292. {
  293. return GetCheckedRadioButton(IDC_RADIO_FILTER_NONE, IDC_RADIO_FILTER_RANGE);
  294. }
  295. void CDNSQueryFilterNamePage::OnRadioClicked()
  296. {
  297. UINT nRadioID = GetSelectedRadioButtonID();
  298. SyncControls(nRadioID);
  299. }
  300. void CDNSQueryFilterNamePage::SyncControls(UINT nRadioID)
  301. {
  302. BOOL bStartsStringEditEnabled = FALSE;
  303. BOOL bContainsStringEditEnabled = FALSE;
  304. BOOL bRangeEnabled = FALSE;
  305. if (nRadioID == IDC_RADIO_FILTER_STARTS)
  306. {
  307. bStartsStringEditEnabled = TRUE;
  308. }
  309. else if (nRadioID == IDC_RADIO_FILTER_CONTAINS)
  310. {
  311. bContainsStringEditEnabled = TRUE;
  312. }
  313. else if (nRadioID == IDC_RADIO_FILTER_RANGE)
  314. {
  315. bRangeEnabled = TRUE;
  316. }
  317. GetStartsStringEdit()->SetReadOnly(!bStartsStringEditEnabled);
  318. GetContainsStringEdit()->SetReadOnly(!bContainsStringEditEnabled);
  319. GetRangeFromStringEdit()->SetReadOnly(!bRangeEnabled);
  320. GetRangeToStringEdit()->SetReadOnly(!bRangeEnabled);
  321. SetDirty();
  322. }
  323. void CDNSQueryFilterNamePage::GetEditText(UINT nID, CString& s)
  324. {
  325. GetDlgItemText(nID, s);
  326. s.TrimLeft();
  327. s.TrimRight();
  328. }
  329. void CDNSQueryFilterNamePage::OnEditChange()
  330. {
  331. SetDirty();
  332. }
  333. BOOL CDNSQueryFilterNamePage::OnInitDialog()
  334. {
  335. CDNSQueryFilterPageBase::OnInitDialog();
  336. // write data to edit fields
  337. SetDlgItemText(IDC_EDIT_FILTER_STARTS, m_pSheet->m_pQueryFilter->m_szStartsString);
  338. SetDlgItemText(IDC_EDIT_FILTER_CONTAINS, m_pSheet->m_pQueryFilter->m_szContainsString);
  339. SetDlgItemText(IDC_EDIT_FILTER_RANGE_FROM, m_pSheet->m_pQueryFilter->m_szRangeFrom);
  340. SetDlgItemText(IDC_EDIT_FILTER_RANGE_TO, m_pSheet->m_pQueryFilter->m_szRangeTo);
  341. // set the radio buttons
  342. UINT nRadioID = IDC_RADIO_FILTER_NONE;
  343. switch(m_pSheet->m_pQueryFilter->m_nFilterOption)
  344. {
  345. case DNS_QUERY_FILTER_NONE:
  346. {
  347. GetRadioNone()->SetCheck(TRUE);
  348. nRadioID = IDC_RADIO_FILTER_NONE;
  349. }
  350. break;
  351. case DNS_QUERY_FILTER_STARTS:
  352. {
  353. GetRadioStarts()->SetCheck(TRUE);
  354. nRadioID = IDC_RADIO_FILTER_STARTS;
  355. }
  356. break;
  357. case DNS_QUERY_FILTER_CONTAINS:
  358. {
  359. GetRadioContains()->SetCheck(TRUE);
  360. nRadioID = IDC_RADIO_FILTER_CONTAINS;
  361. }
  362. break;
  363. case DNS_QUERY_FILTER_RANGE:
  364. {
  365. GetRadioRange()->SetCheck(TRUE);
  366. nRadioID = IDC_RADIO_FILTER_RANGE;
  367. }
  368. break;
  369. default:
  370. ASSERT(FALSE);
  371. }
  372. // enable/disable the edit fields
  373. SyncControls(nRadioID);
  374. Init();
  375. return TRUE; // return TRUE unless you set the focus to a control
  376. }
  377. BOOL CDNSQueryFilterNamePage::OnApply()
  378. {
  379. if (!IsDirty())
  380. return TRUE;
  381. UINT nRadioID = GetSelectedRadioButtonID();
  382. // get data from edit controls
  383. GetEditText(IDC_EDIT_FILTER_STARTS, m_pSheet->m_pQueryFilter->m_szStartsString);
  384. GetEditText(IDC_EDIT_FILTER_CONTAINS, m_pSheet->m_pQueryFilter->m_szContainsString);
  385. GetEditText(IDC_EDIT_FILTER_RANGE_FROM, m_pSheet->m_pQueryFilter->m_szRangeFrom);
  386. GetEditText(IDC_EDIT_FILTER_RANGE_TO, m_pSheet->m_pQueryFilter->m_szRangeTo);
  387. // get radio button selection
  388. switch(nRadioID)
  389. {
  390. case IDC_RADIO_FILTER_NONE:
  391. {
  392. m_pSheet->m_pQueryFilter->m_nFilterOption = DNS_QUERY_FILTER_NONE;
  393. }
  394. break;
  395. case IDC_RADIO_FILTER_STARTS:
  396. {
  397. if (m_pSheet->m_pQueryFilter->m_szStartsString.IsEmpty())
  398. m_pSheet->m_pQueryFilter->m_nFilterOption = DNS_QUERY_FILTER_NONE;
  399. else
  400. m_pSheet->m_pQueryFilter->m_nFilterOption = DNS_QUERY_FILTER_STARTS;
  401. }
  402. break;
  403. case IDC_RADIO_FILTER_CONTAINS:
  404. {
  405. if (m_pSheet->m_pQueryFilter->m_szContainsString.IsEmpty())
  406. m_pSheet->m_pQueryFilter->m_nFilterOption = DNS_QUERY_FILTER_NONE;
  407. else
  408. m_pSheet->m_pQueryFilter->m_nFilterOption = DNS_QUERY_FILTER_CONTAINS;
  409. }
  410. break;
  411. case IDC_RADIO_FILTER_RANGE:
  412. {
  413. if (m_pSheet->m_pQueryFilter->m_szRangeFrom.IsEmpty() &&
  414. m_pSheet->m_pQueryFilter->m_szRangeTo.IsEmpty() )
  415. m_pSheet->m_pQueryFilter->m_nFilterOption = DNS_QUERY_FILTER_NONE;
  416. else
  417. m_pSheet->m_pQueryFilter->m_nFilterOption = DNS_QUERY_FILTER_RANGE;
  418. }
  419. break;
  420. default:
  421. ASSERT(FALSE);
  422. }
  423. return TRUE;
  424. }
  425. //////////////////////////////////////////////////////////////////////
  426. // CDNSQueryFilterAdvancedPage IMPLEMENTATION
  427. BEGIN_MESSAGE_MAP(CDNSQueryFilterAdvancedPage, CDNSQueryFilterPageBase)
  428. ON_EN_CHANGE(IDC_EDIT_COUNT, OnCountEditChange)
  429. END_MESSAGE_MAP()
  430. void CDNSQueryFilterAdvancedPage::OnCountEditChange()
  431. {
  432. SetDirty();
  433. }
  434. BOOL CDNSQueryFilterAdvancedPage::OnInitDialog()
  435. {
  436. CDNSQueryFilterPageBase::OnInitDialog();
  437. // set the range of the edit control for range validation
  438. VERIFY(m_maxCountEdit.SubclassDlgItem(IDC_EDIT_COUNT, this));
  439. m_maxCountEdit.SetRange(DNS_QUERY_OBJ_COUNT_MIN, DNS_QUERY_OBJ_COUNT_MAX);
  440. // Disable IME support on the control
  441. ImmAssociateContext(m_maxCountEdit.GetSafeHwnd(), NULL);
  442. // set limit on the # of digits based on the max value
  443. CString s;
  444. s.Format(_T("%u"), DNS_QUERY_OBJ_COUNT_MAX);
  445. m_maxCountEdit.LimitText(s.GetLength());
  446. // set the value
  447. m_maxCountEdit.SetVal(m_pSheet->m_pQueryFilter->m_nMaxObjectCount);
  448. Init();
  449. return TRUE;
  450. }
  451. BOOL CDNSQueryFilterAdvancedPage::OnApply()
  452. {
  453. if (!IsDirty())
  454. return TRUE;
  455. m_pSheet->m_pQueryFilter->m_nMaxObjectCount = m_maxCountEdit.GetVal();
  456. return TRUE;
  457. }
  458. //////////////////////////////////////////////////////////////////////
  459. // CDNSQueryFilter
  460. BOOL CDNSQueryFilter::EditFilteringOptions(CComponentDataObject* pComponentData)
  461. {
  462. CThemeContextActivator activator;
  463. CDNSQueryFilterSheet dlg(this, pComponentData);
  464. return IDOK == dlg.DoModal();
  465. }
  466. HRESULT CDNSQueryFilter::Load(IStream* pStm)
  467. {
  468. HRESULT hr;
  469. // name filtering
  470. if (FAILED(hr = LoadDWordHelper(pStm, (DWORD*)(&m_nFilterOption))))
  471. return hr;
  472. if (FAILED(hr = LoadStringHelper(m_szStartsString, pStm)))
  473. return hr;
  474. if (FAILED(hr = LoadStringHelper(m_szContainsString, pStm)))
  475. return hr;
  476. if (FAILED(hr = LoadStringHelper(m_szRangeFrom, pStm)))
  477. return hr;
  478. if (FAILED(hr = LoadStringHelper(m_szRangeTo, pStm)))
  479. return hr;
  480. // query limit
  481. if (FAILED(hr = LoadDWordHelper(pStm, (DWORD*)(&m_nMaxObjectCount))))
  482. return hr;
  483. return LoadDWordHelper(pStm, (DWORD*)(&m_bGetAll));
  484. }
  485. HRESULT CDNSQueryFilter::Save(IStream* pStm)
  486. {
  487. HRESULT hr;
  488. // name filtering
  489. if (FAILED(hr = SaveDWordHelper(pStm, (DWORD)m_nFilterOption)))
  490. return hr;
  491. if (FAILED(hr = SaveStringHelper(m_szStartsString, pStm)))
  492. return hr;
  493. if (FAILED(hr = SaveStringHelper(m_szContainsString, pStm)))
  494. return hr;
  495. if (FAILED(hr = SaveStringHelper(m_szRangeFrom, pStm)))
  496. return hr;
  497. if (FAILED(hr = SaveStringHelper(m_szRangeTo, pStm)))
  498. return hr;
  499. // query limit
  500. if (FAILED(hr = SaveDWordHelper(pStm, (DWORD)(m_nMaxObjectCount))))
  501. return hr;
  502. return SaveDWordHelper(pStm, (DWORD)(m_bGetAll));
  503. }
  504. //////////////////////////////////////////////////////////////////////
  505. // CDNSRootData
  506. const GUID CDNSRootData::NodeTypeGUID =
  507. { 0x2faebfa3, 0x3f1a, 0x11d0, { 0x8c, 0x65, 0x0, 0xc0, 0x4f, 0xd8, 0xfe, 0xcb } };
  508. BEGIN_TOOLBAR_MAP(CDNSRootData)
  509. TOOLBAR_EVENT(toolbarNewServer, OnConnectToServer)
  510. END_TOOLBAR_MAP()
  511. CDNSRootData::CDNSRootData(CComponentDataObject* pComponentData) : CRootData(pComponentData)
  512. {
  513. m_bAdvancedView = FALSE;
  514. m_pColumnSet = NULL;
  515. m_szDescriptionBar = _T("");
  516. m_bCreatePTRWithHost = FALSE;
  517. }
  518. CDNSRootData::~CDNSRootData()
  519. {
  520. TRACE(_T("~CDNSRootData(), name <%s>\n"),GetDisplayName());
  521. }
  522. STDAPI DnsSetup(LPCWSTR lpszFwdZoneName,
  523. LPCWSTR lpszFwdZoneFileName,
  524. LPCWSTR lpszRevZoneName,
  525. LPCWSTR lpszRevZoneFileName,
  526. DWORD dwFlags);
  527. BOOL CDNSRootData::OnAddMenuItem(LPCONTEXTMENUITEM2 pContextMenuItem2,
  528. long*)
  529. {
  530. CComponentDataObject* pComponentData = GetComponentDataObject();
  531. if (pContextMenuItem2->lCommandID == IDM_SNAPIN_CONNECT_TO_SERVER)
  532. {
  533. ASSERT(pComponentData != NULL);
  534. if (pComponentData->IsExtensionSnapin())
  535. return FALSE; // extensions do not have this menu item
  536. return TRUE;
  537. }
  538. // add toggle menu item for advanced view
  539. if (pContextMenuItem2->lCommandID == IDM_SNAPIN_ADVANCED_VIEW)
  540. {
  541. pContextMenuItem2->fFlags = IsAdvancedView() ? MF_CHECKED : 0;
  542. }
  543. if (pContextMenuItem2->lCommandID == IDM_SNAPIN_FILTERING)
  544. {
  545. if (IsFilteringEnabled())
  546. {
  547. pContextMenuItem2->fFlags = MF_CHECKED;
  548. }
  549. return TRUE;
  550. }
  551. return TRUE;
  552. }
  553. HRESULT CDNSRootData::GetResultViewType(CComponentDataObject*,
  554. LPOLESTR *ppViewType,
  555. long *pViewOptions)
  556. {
  557. HRESULT hr = S_FALSE;
  558. if (m_containerChildList.IsEmpty() && m_leafChildList.IsEmpty())
  559. {
  560. *pViewOptions = MMC_VIEW_OPTIONS_NOLISTVIEWS;
  561. LPOLESTR psz = NULL;
  562. StringFromCLSID(CLSID_MessageView, &psz);
  563. USES_CONVERSION;
  564. if (psz != NULL)
  565. {
  566. *ppViewType = psz;
  567. hr = S_OK;
  568. }
  569. }
  570. else
  571. {
  572. *pViewOptions = MMC_VIEW_OPTIONS_NONE;
  573. *ppViewType = NULL;
  574. hr = S_FALSE;
  575. }
  576. return hr;
  577. }
  578. HRESULT CDNSRootData::OnShow(LPCONSOLE lpConsole)
  579. {
  580. CComPtr<IUnknown> spUnknown;
  581. CComPtr<IMessageView> spMessageView;
  582. HRESULT hr = lpConsole->QueryResultView(&spUnknown);
  583. if (FAILED(hr))
  584. return S_OK;
  585. hr = spUnknown->QueryInterface(IID_IMessageView, (PVOID*)&spMessageView);
  586. if (SUCCEEDED(hr))
  587. {
  588. // Load and set the title text of the message view
  589. CString szTitle;
  590. VERIFY(szTitle.LoadString(IDS_MESSAGE_VIEW_NO_SERVER_TITLE));
  591. spMessageView->SetTitleText(szTitle);
  592. // Load and set the body text of the message view
  593. CString szMessage;
  594. VERIFY(szMessage.LoadString(IDS_MESSAGE_VIEW_NO_SERVER_MESSAGE));
  595. spMessageView->SetBodyText(szMessage);
  596. // Use the standard information icon
  597. spMessageView->SetIcon(Icon_Information);
  598. }
  599. return S_OK;
  600. }
  601. BOOL CDNSRootData::IsFilteringEnabled()
  602. {
  603. UINT nFilterOption = GetFilter()->GetFilterOption();
  604. if (nFilterOption == DNS_QUERY_FILTER_DISABLED || nFilterOption == DNS_QUERY_FILTER_NONE)
  605. {
  606. return FALSE;
  607. }
  608. return TRUE;
  609. }
  610. BOOL CDNSRootData::OnSetRefreshVerbState(DATA_OBJECT_TYPES,
  611. BOOL* pbHide,
  612. CNodeList*)
  613. {
  614. *pbHide = FALSE;
  615. return !IsThreadLocked();
  616. }
  617. HRESULT CDNSRootData::OnSetToolbarVerbState(IToolbar* pToolbar,
  618. CNodeList*)
  619. {
  620. HRESULT hr = S_OK;
  621. //
  622. // Set the button state for each button on the toolbar
  623. //
  624. hr = pToolbar->SetButtonState(toolbarNewServer, ENABLED, TRUE);
  625. ASSERT(SUCCEEDED(hr));
  626. hr = pToolbar->SetButtonState(toolbarNewRecord, ENABLED, FALSE);
  627. ASSERT(SUCCEEDED(hr));
  628. hr = pToolbar->SetButtonState(toolbarNewZone, ENABLED, FALSE);
  629. ASSERT(SUCCEEDED(hr));
  630. return hr;
  631. }
  632. HRESULT CDNSRootData::OnCommand(long nCommandID,
  633. DATA_OBJECT_TYPES,
  634. CComponentDataObject* pComponentData,
  635. CNodeList* pNodeList)
  636. {
  637. if (pNodeList->GetCount() > 1) // multiple selection
  638. {
  639. return E_FAIL;
  640. }
  641. switch (nCommandID)
  642. {
  643. case IDM_SNAPIN_CONNECT_TO_SERVER:
  644. OnConnectToServer(pComponentData, pNodeList);
  645. break;
  646. case IDM_SNAPIN_ADVANCED_VIEW:
  647. OnViewOptions(pComponentData);
  648. break;
  649. case IDM_SNAPIN_FILTERING:
  650. {
  651. if (OnFilteringOptions(pComponentData))
  652. {
  653. pComponentData->SetDescriptionBarText(this);
  654. }
  655. }
  656. break;
  657. default:
  658. ASSERT(FALSE); // Unknown command!
  659. return E_FAIL;
  660. }
  661. return S_OK;
  662. }
  663. BOOL CDNSRootData::OnEnumerate(CComponentDataObject* pComponentData, BOOL)
  664. {
  665. if (m_containerChildList.IsEmpty())
  666. {
  667. // the list is empty, need to add
  668. ASSERT(pComponentData != NULL);
  669. // create a modal dialog + possibly the wizard proper
  670. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  671. CDNSServerWizardHolder holder(this, pComponentData, NULL);
  672. holder.DoModalConnectOnLocalComputer();
  673. return FALSE;
  674. }
  675. return TRUE; // there are already children, add them to the UI now
  676. }
  677. #define DNS_STREAM_VERSION_W2K ((DWORD)0x06)
  678. #define DNS_STREAM_VERSION ((DWORD)0x07)
  679. // IStream manipulation helpers overrides
  680. HRESULT CDNSRootData::Load(IStream* pStm)
  681. {
  682. // assume never get multiple loads
  683. if(!m_containerChildList.IsEmpty() || !m_leafChildList.IsEmpty())
  684. return E_FAIL;
  685. WCHAR szBuffer[256];
  686. ULONG nLen; // WCHAR counting NULL
  687. UINT nCount;
  688. ULONG cbRead;
  689. // read the version ##
  690. DWORD dwVersion;
  691. VERIFY(SUCCEEDED(pStm->Read((void*)&dwVersion,sizeof(DWORD), &cbRead)));
  692. ASSERT(cbRead == sizeof(DWORD));
  693. if (dwVersion != DNS_STREAM_VERSION && dwVersion != DNS_STREAM_VERSION_W2K)
  694. return E_FAIL;
  695. // load filtering options
  696. VERIFY(SUCCEEDED(m_filterObj.Load(pStm)));
  697. // load view option
  698. VERIFY(SUCCEEDED(pStm->Read((void*)&m_bAdvancedView,sizeof(BOOL), &cbRead)));
  699. ASSERT(cbRead == sizeof(BOOL));
  700. //
  701. // load the Create PTR record with host flag
  702. //
  703. if (dwVersion > DNS_STREAM_VERSION_W2K)
  704. {
  705. VERIFY(SUCCEEDED(pStm->Read((void*)&m_bCreatePTRWithHost,sizeof(BOOL), &cbRead)));
  706. ASSERT(cbRead == sizeof(BOOL));
  707. }
  708. // load the name of the snapin root display string
  709. VERIFY(SUCCEEDED(pStm->Read((void*)&nLen,sizeof(DWORD), &cbRead)));
  710. ASSERT(cbRead == sizeof(UINT));
  711. VERIFY(SUCCEEDED(pStm->Read((void*)szBuffer,sizeof(WCHAR)*nLen, &cbRead)));
  712. ASSERT(cbRead == sizeof(WCHAR)*nLen);
  713. SetDisplayName(szBuffer);
  714. // load the list of servers
  715. VERIFY(SUCCEEDED(pStm->Read((void*)&nCount,sizeof(DWORD), &cbRead)));
  716. ASSERT(cbRead == sizeof(UINT));
  717. CComponentDataObject* pComponentData = GetComponentDataObject();
  718. for (int k=0; k< (int)nCount; k++)
  719. {
  720. CDNSServerNode* p = NULL;
  721. VERIFY(SUCCEEDED(CDNSServerNode::CreateFromStream(pStm, &p)));
  722. ASSERT(p != NULL);
  723. VERIFY(AddChildToList(p));
  724. AddServerToThreadList(p, pComponentData);
  725. }
  726. if (nCount > 0)
  727. MarkEnumerated();
  728. ASSERT(m_containerChildList.GetCount() == (int)nCount);
  729. return S_OK;
  730. }
  731. HRESULT CDNSRootData::Save(IStream* pStm, BOOL fClearDirty)
  732. {
  733. DWORD nCount = 0;
  734. ULONG cbWrite = 0;
  735. // write the version ##
  736. DWORD dwVersion = DNS_STREAM_VERSION;
  737. VERIFY(SUCCEEDED(pStm->Write((void*)&dwVersion, sizeof(DWORD),&cbWrite)));
  738. ASSERT(cbWrite == sizeof(DWORD));
  739. // save filtering options
  740. VERIFY(SUCCEEDED(m_filterObj.Save(pStm)));
  741. // save view options
  742. VERIFY(SUCCEEDED(pStm->Write((void*)&m_bAdvancedView, sizeof(BOOL),&cbWrite)));
  743. ASSERT(cbWrite == sizeof(BOOL));
  744. //
  745. // save the create PTR record with host flag
  746. //
  747. VERIFY(SUCCEEDED(pStm->Write((void*)&m_bCreatePTRWithHost, sizeof(BOOL),&cbWrite)));
  748. ASSERT(cbWrite == sizeof(BOOL));
  749. // save the name of the snapin root display string
  750. DWORD nLen = static_cast<DWORD>(wcslen(GetDisplayName())+1); // WCHAR including NULL
  751. VERIFY(SUCCEEDED(pStm->Write((void*)&nLen, sizeof(DWORD),&cbWrite)));
  752. ASSERT(cbWrite == sizeof(DWORD));
  753. VERIFY(SUCCEEDED(pStm->Write((void*)(GetDisplayName()), sizeof(WCHAR)*nLen,&cbWrite)));
  754. ASSERT(cbWrite == sizeof(WCHAR)*nLen);
  755. // write # of servers
  756. nCount = (DWORD)m_containerChildList.GetCount();
  757. VERIFY(SUCCEEDED(pStm->Write((void*)&nCount, sizeof(DWORD),&cbWrite)));
  758. ASSERT(cbWrite == sizeof(DWORD));
  759. // loop through the list of servers and serialize them
  760. POSITION pos;
  761. for (pos = m_containerChildList.GetHeadPosition(); pos != NULL; )
  762. {
  763. CDNSServerNode* pServerNode = (CDNSServerNode*)m_containerChildList.GetNext(pos);
  764. VERIFY(SUCCEEDED(pServerNode->SaveToStream(pStm)));
  765. }
  766. if (fClearDirty)
  767. SetDirtyFlag(FALSE);
  768. return S_OK;
  769. }
  770. HRESULT CDNSRootData::IsDirty()
  771. {
  772. return CRootData::IsDirty();
  773. }
  774. HRESULT CDNSRootData::OnConnectToServer(CComponentDataObject* pComponentData,
  775. CNodeList*)
  776. {
  777. ASSERT(pComponentData != NULL);
  778. // create a modal dialog + possibly the wizard proper
  779. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  780. CDNSServerWizardHolder holder(this, pComponentData, NULL);
  781. holder.DoModalConnect();
  782. pComponentData->UpdateResultPaneView(this);
  783. return S_OK;
  784. }
  785. void CDNSRootData::AddServer(CDNSServerNode* p, CComponentDataObject* pComponentData)
  786. {
  787. ASSERT(p != NULL);
  788. AddChildToListAndUISorted(p, pComponentData);
  789. AddServerToThreadList(p, pComponentData);
  790. pComponentData->UpdateResultPaneView(this);
  791. pComponentData->SetDescriptionBarText(this);
  792. }
  793. BOOL CDNSRootData::VerifyServerName(LPCTSTR lpszServerName)
  794. {
  795. POSITION pos;
  796. for (pos = m_containerChildList.GetHeadPosition(); pos != NULL; )
  797. {
  798. CTreeNode* pNode = m_containerChildList.GetNext(pos);
  799. ASSERT(pNode->IsContainer());
  800. //
  801. // case insensitive compare
  802. //
  803. if (_wcsicmp(pNode->GetDisplayName(), lpszServerName) == 0)
  804. {
  805. return FALSE;
  806. }
  807. }
  808. return TRUE;
  809. }
  810. BOOL CDNSRootData::OnViewOptions(CComponentDataObject* pComponentData)
  811. {
  812. // make sure there are not property sheets up: we do this because:
  813. // a) some folders might be removed and might have sheets up
  814. // b) some RR property pages (PTR) might not be switchable
  815. // on the fly between view types
  816. if (IsSheetLocked())
  817. {
  818. if (!CanCloseSheets())
  819. return TRUE;
  820. pComponentData->GetPropertyPageHolderTable()->DeleteSheetsOfNode(this);
  821. }
  822. ASSERT(!IsSheetLocked());
  823. // toggle the view state
  824. m_bAdvancedView = !m_bAdvancedView;
  825. // loop through the servers
  826. POSITION pos;
  827. for (pos = m_containerChildList.GetHeadPosition(); pos != NULL; )
  828. {
  829. CTreeNode* pNode = m_containerChildList.GetNext(pos);
  830. ASSERT(pNode->IsContainer());
  831. CDNSServerNode* pServerNode = (CDNSServerNode*)pNode;
  832. // pass the new view option
  833. pServerNode->ChangeViewOption(m_bAdvancedView, pComponentData);
  834. }
  835. // dirty the MMC document
  836. SetDirtyFlag(TRUE);
  837. return TRUE;
  838. }
  839. BOOL CDNSRootData::OnFilteringOptions(CComponentDataObject* pComponentData)
  840. {
  841. BOOL bRet = m_filterObj.EditFilteringOptions(pComponentData);
  842. if (bRet)
  843. {
  844. SetDirtyFlag(TRUE);
  845. }
  846. return bRet;
  847. }
  848. BOOL CDNSRootData::CanCloseSheets()
  849. {
  850. // NTRAID#NTBUG-594003-2002/04/11-JeffJon-Don't offer
  851. // to shutdown the sheets for the user because if the
  852. // sheet brought up a modal dialog we will deadlock
  853. // ourselves.
  854. DNSMessageBox(IDS_MSG_CONT_CLOSE_SHEET, MB_OK);
  855. return FALSE;
  856. }
  857. BOOL CDNSRootData::OnRefresh(CComponentDataObject* pComponentData,
  858. CNodeList* pNodeList)
  859. {
  860. if (pNodeList->GetCount() > 1) // multiple selection
  861. {
  862. BOOL bRet = TRUE;
  863. POSITION pos = pNodeList->GetHeadPosition();
  864. while (pos != NULL)
  865. {
  866. CTreeNode* pNode = pNodeList->GetNext(pos);
  867. ASSERT(pNode != NULL);
  868. CNodeList nodeList;
  869. nodeList.AddTail(pNode);
  870. if (!pNode->OnRefresh(pComponentData, &nodeList))
  871. {
  872. bRet = FALSE;
  873. }
  874. }
  875. return bRet;
  876. }
  877. if (IsSheetLocked())
  878. {
  879. if (!CanCloseSheets())
  880. return FALSE;
  881. pComponentData->GetPropertyPageHolderTable()->DeleteSheetsOfNode(this);
  882. }
  883. ASSERT(!IsSheetLocked());
  884. POSITION pos;
  885. for (pos = m_containerChildList.GetHeadPosition(); pos != NULL; )
  886. {
  887. CTreeNode* pNode = m_containerChildList.GetNext(pos);
  888. ASSERT(pNode->IsContainer());
  889. CNodeList nodeList;
  890. nodeList.AddTail(pNode);
  891. ((CDNSServerNode*)pNode)->OnRefresh(pComponentData, &nodeList);
  892. }
  893. return TRUE;
  894. }
  895. LPWSTR CDNSRootData::GetDescriptionBarText()
  896. {
  897. static CString szFilterEnabled;
  898. static CString szServersFormat;
  899. INT_PTR nContainerCount = GetContainerChildList()->GetCount();
  900. INT_PTR nLeafCount = GetLeafChildList()->GetCount();
  901. //
  902. // If not already loaded, then load the format string L"%d record(s)"
  903. //
  904. if (szServersFormat.IsEmpty())
  905. {
  906. szServersFormat.LoadString(IDS_FORMAT_SERVERS);
  907. }
  908. //
  909. // Format the child count into the description bar text
  910. //
  911. m_szDescriptionBar.Format(szServersFormat, nContainerCount + nLeafCount);
  912. //
  913. // Add L"[Filter Activated]" if the filter is on
  914. //
  915. if(IsFilteringEnabled())
  916. {
  917. //
  918. // If not already loaded, then load the L"[Filter Activated]" string
  919. //
  920. if (szFilterEnabled.IsEmpty())
  921. {
  922. szFilterEnabled.LoadString(IDS_FILTER_ENABLED);
  923. }
  924. m_szDescriptionBar += szFilterEnabled;
  925. }
  926. return (LPWSTR)(LPCWSTR)m_szDescriptionBar;
  927. }
  928. void CDNSRootData::TestServers(DWORD dwCurrTime, DWORD dwTimeInterval,
  929. CComponentDataObject* pComponentData)
  930. {
  931. //TRACE(_T("CDNSRootData::TestServers()\n"));
  932. POSITION pos;
  933. for (pos = m_containerChildList.GetHeadPosition(); pos != NULL; )
  934. {
  935. CTreeNode* pNode = m_containerChildList.GetNext(pos);
  936. ASSERT(pNode->IsContainer());
  937. CDNSServerNode* pServerNode = (CDNSServerNode*)pNode;
  938. if (pServerNode->IsTestEnabled() && !pServerNode->m_bTestQueryPending
  939. && (pServerNode->m_dwTestTime <= dwCurrTime))
  940. {
  941. DWORD dwQueryFlags =
  942. CDNSServerTestQueryResult::Pack(pServerNode->IsTestSimpleQueryEnabled(),
  943. pServerNode->IsRecursiveQueryEnabled());
  944. pComponentData->PostMessageToTimerThread(WM_TIMER_THREAD_SEND_QUERY,
  945. (WPARAM)pServerNode,
  946. (WPARAM)dwQueryFlags);
  947. pServerNode->m_dwTestTime = dwCurrTime + pServerNode->GetTestInterval();
  948. }
  949. }
  950. // check if the time counter has wrapped (it should be very unlikely, because
  951. // the timeline is on a DWORD in seconds (about 47000 days) from the console startup.
  952. if ((dwCurrTime + dwTimeInterval) < dwCurrTime)
  953. {
  954. // just reset the whole set of server times (not accurate, but acceptable)
  955. for (pos = m_containerChildList.GetHeadPosition(); pos != NULL; )
  956. {
  957. CTreeNode* pNode = m_containerChildList.GetNext(pos);
  958. ASSERT(pNode->IsContainer());
  959. CDNSServerNode* pServerNode = (CDNSServerNode*)pNode;
  960. pServerNode->m_dwTestTime = 0;
  961. }
  962. }
  963. }
  964. void CDNSRootData::OnServerTestData(WPARAM wParam, LPARAM lParam, CComponentDataObject* pComponentData)
  965. {
  966. ASSERT(lParam == 0);
  967. CDNSServerTestQueryResult* pTestResult = (CDNSServerTestQueryResult*)wParam;
  968. ASSERT(pTestResult != NULL);
  969. // loop through the list of servers to find where it belongs
  970. POSITION pos;
  971. for (pos = m_containerChildList.GetHeadPosition(); pos != NULL; )
  972. {
  973. CTreeNode* pNode = m_containerChildList.GetNext(pos);
  974. ASSERT(pNode->IsContainer());
  975. CDNSServerNode* pServerNode = (CDNSServerNode*)pNode;
  976. if ( (CDNSServerNode*)(pTestResult->m_serverCookie) == pServerNode)
  977. {
  978. pServerNode->AddTestQueryResult(pTestResult, pComponentData);
  979. return;
  980. }
  981. }
  982. }
  983. void CDNSRootData::AddServerToThreadList(CDNSServerNode* pServerNode,
  984. CComponentDataObject* pComponentData)
  985. {
  986. CDNSServerTestQueryInfo* pInfo = new CDNSServerTestQueryInfo;
  987. if (pInfo)
  988. {
  989. pInfo->m_szServerName = pServerNode->GetDisplayName();
  990. pInfo->m_serverCookie = (MMC_COOKIE)pServerNode;
  991. pComponentData->PostMessageToTimerThread(WM_TIMER_THREAD_ADD_SERVER, (WPARAM)pInfo,0);
  992. }
  993. }
  994. void CDNSRootData::RemoveServerFromThreadList(CDNSServerNode* pServerNode,
  995. CComponentDataObject* pComponentData)
  996. {
  997. WPARAM serverCookie = (WPARAM)pServerNode;
  998. pComponentData->PostMessageToTimerThread(WM_TIMER_THREAD_REMOVE_SERVER, serverCookie,0);
  999. }
  1000. ///////////////////////////////////////////////////////////////////
  1001. // CDNSServerTestTimerThread
  1002. int CDNSServerTestTimerThread::Run()
  1003. {
  1004. MSG msg;
  1005. // initialize the message pump
  1006. ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
  1007. // get let the main thread know we are entering the loop
  1008. // (0,0) means just acknowkedge
  1009. PostMessageToWnd(0,0);
  1010. while(::GetMessage(&msg, NULL, 0, 0))
  1011. {
  1012. switch(msg.message)
  1013. {
  1014. case WM_TIMER_THREAD_SEND_QUERY:
  1015. case WM_TIMER_THREAD_SEND_QUERY_TEST_NOW:
  1016. {
  1017. MMC_COOKIE serverCookie = (MMC_COOKIE)msg.wParam;
  1018. ASSERT(serverCookie != NULL);
  1019. POSITION pos;
  1020. for (pos = m_serverInfoList.GetHeadPosition(); pos != NULL; )
  1021. {
  1022. CDNSServerTestQueryInfo* pCurrInfo =
  1023. (CDNSServerTestQueryInfo*)m_serverInfoList.GetNext(pos);
  1024. if (serverCookie == pCurrInfo->m_serverCookie)
  1025. {
  1026. OnExecuteQuery(pCurrInfo, (DWORD)msg.lParam,
  1027. (msg.message == WM_TIMER_THREAD_SEND_QUERY_TEST_NOW));
  1028. break;
  1029. }
  1030. }
  1031. }
  1032. break;
  1033. case WM_TIMER_THREAD_ADD_SERVER:
  1034. {
  1035. CDNSServerTestQueryInfo* pInfo = (CDNSServerTestQueryInfo*)msg.wParam;
  1036. ASSERT(pInfo != NULL);
  1037. m_serverInfoList.AddTail(pInfo);
  1038. }
  1039. break;
  1040. case WM_TIMER_THREAD_REMOVE_SERVER:
  1041. {
  1042. MMC_COOKIE serverCookie = (MMC_COOKIE)msg.wParam;
  1043. ASSERT(serverCookie != NULL);
  1044. POSITION pos;
  1045. POSITION posDel = NULL;
  1046. CDNSServerTestQueryInfo* pInfo = NULL;
  1047. for (pos = m_serverInfoList.GetHeadPosition(); pos != NULL; )
  1048. {
  1049. posDel = pos;
  1050. CDNSServerTestQueryInfo* pCurrInfo =
  1051. (CDNSServerTestQueryInfo*)m_serverInfoList.GetNext(pos);
  1052. if (serverCookie == pCurrInfo->m_serverCookie)
  1053. {
  1054. pInfo = pCurrInfo;
  1055. break;
  1056. }
  1057. }
  1058. if (pInfo != NULL)
  1059. {
  1060. ASSERT(posDel != NULL);
  1061. m_serverInfoList.RemoveAt(posDel);
  1062. delete pInfo;
  1063. }
  1064. }
  1065. break;
  1066. //default:
  1067. //ASSERT(FALSE);
  1068. }
  1069. }
  1070. return 0;
  1071. }
  1072. void CDNSServerTestTimerThread::OnExecuteQuery(CDNSServerTestQueryInfo* pInfo,
  1073. DWORD dwQueryFlags,
  1074. BOOL bAsyncQuery)
  1075. {
  1076. // initialize a query result object
  1077. CDNSServerTestQueryResult* pTestResult = new CDNSServerTestQueryResult;
  1078. if (!pTestResult)
  1079. {
  1080. return;
  1081. }
  1082. pTestResult->m_serverCookie = pInfo->m_serverCookie;
  1083. pTestResult->m_dwQueryFlags = dwQueryFlags;
  1084. pTestResult->m_bAsyncQuery = bAsyncQuery;
  1085. ::GetLocalTime(&(pTestResult->m_queryTime));
  1086. // execute query
  1087. BOOL bPlainQuery, bRecursiveQuery;
  1088. CDNSServerTestQueryResult::Unpack(dwQueryFlags, &bPlainQuery, &bRecursiveQuery);
  1089. IP_ADDRESS* ipArray;
  1090. int nIPCount;
  1091. pTestResult->m_dwAddressResolutionResult = FindIP(pInfo->m_szServerName, &ipArray, &nIPCount);
  1092. if (pTestResult->m_dwAddressResolutionResult == 0)
  1093. {
  1094. ASSERT(ipArray != NULL);
  1095. ASSERT(nIPCount > 0);
  1096. PIP_ARRAY pipArr = (PIP_ARRAY)malloc(sizeof(DWORD)+sizeof(IP_ADDRESS)*nIPCount);
  1097. if (pipArr && ipArray)
  1098. {
  1099. pipArr->AddrCount = nIPCount;
  1100. memcpy(pipArr->AddrArray, ipArray, sizeof(IP_ADDRESS)*nIPCount);
  1101. if (bPlainQuery)
  1102. {
  1103. pTestResult->m_dwPlainQueryResult = DoNothingQuery(pipArr, TRUE);
  1104. }
  1105. if (bRecursiveQuery)
  1106. {
  1107. pTestResult->m_dwRecursiveQueryResult = DoNothingQuery(pipArr, FALSE);
  1108. }
  1109. free(pipArr);
  1110. pipArr = 0;
  1111. }
  1112. }
  1113. if (!PostMessageToWnd((WPARAM)pTestResult, 0))
  1114. delete pTestResult; // could not deliver
  1115. if (ipArray != NULL)
  1116. free(ipArray);
  1117. }
  1118. DNS_STATUS CDNSServerTestTimerThread::FindIP(LPCTSTR lpszServerName, IP_ADDRESS** pipArray, int* pnIPCount)
  1119. {
  1120. DNS_STATUS dwErr = 0;
  1121. *pipArray = NULL;
  1122. *pnIPCount = 0;
  1123. // try to see if the name is already an IP address
  1124. IP_ADDRESS ipAddr = IPStringToAddr(lpszServerName);
  1125. if (ipAddr != INADDR_NONE)
  1126. {
  1127. *pnIPCount = 1;
  1128. *pipArray = (IP_ADDRESS*)malloc((*pnIPCount)*sizeof(IP_ADDRESS));
  1129. if (*pipArray != NULL)
  1130. {
  1131. *pipArray[0] = ipAddr;
  1132. }
  1133. }
  1134. else
  1135. {
  1136. //
  1137. // Originally we were doing a DnsQuery() to retrieve the IP address of the server so that we
  1138. // could perform a query to that server to monitor its response. The problem with this is that
  1139. // if the user enters a single label hostname as the server and they are administering remotely
  1140. // and the two machines have different domain suffixes, then the DnsQuery() to get the IP address
  1141. // of the server would fail. DnsQuery() appends the name of the Domain suffix to the single label
  1142. // host name and then tries to resolve the using that FQDN which is incorrect. So instead of
  1143. // performing a DnsQuery() to get the IP address, the following uses WSALookupServiceBegin(),
  1144. // Next(), and End() to get the IP address. This has a better chance of resolving the name because
  1145. // it uses DNS, WINS, etc. I am leaving in the old stuff just in case we run into some problems.
  1146. //
  1147. HANDLE hLookup;
  1148. WSAQUERYSET qsQuery;
  1149. DWORD dwBufLen = 0;
  1150. GUID gHostAddrByName = SVCID_INET_HOSTADDRBYNAME;
  1151. WSAQUERYSET* pBuffer = NULL;
  1152. //
  1153. // Initialize the query structure
  1154. //
  1155. memset(&qsQuery, 0, sizeof(WSAQUERYSET));
  1156. qsQuery.dwSize = sizeof(WSAQUERYSET); // the dwSize field has to be initialised like this
  1157. qsQuery.dwNameSpace = NS_ALL;
  1158. qsQuery.lpServiceClassId = &gHostAddrByName; // this is the GUID to perform forward name resolution (name to IP)
  1159. qsQuery.lpszServiceInstanceName = (LPWSTR)lpszServerName; // this is the name queried for.
  1160. hLookup = NULL;
  1161. //
  1162. // Get the handle for the query
  1163. //
  1164. int iStartupRet = 0;
  1165. int iResult = WSALookupServiceBegin(&qsQuery,LUP_RETURN_ALL,&hLookup);
  1166. if (iResult != 0)
  1167. {
  1168. //
  1169. // Find out what socket error it was
  1170. //
  1171. int iErrorRet = WSAGetLastError();
  1172. //
  1173. // If the service wasn't started try starting it
  1174. //
  1175. if (iErrorRet == WSANOTINITIALISED)
  1176. {
  1177. WSADATA wsaData;
  1178. WORD wVersion = MAKEWORD(2,0);
  1179. iStartupRet = WSAStartup(wVersion, &wsaData);
  1180. if (iStartupRet == 0)
  1181. {
  1182. //
  1183. // Startup succeeded, lets try to begin again
  1184. //
  1185. iResult = WSALookupServiceBegin(&qsQuery,LUP_RETURN_ALL,&hLookup);
  1186. }
  1187. }
  1188. //
  1189. // Clear the error
  1190. //
  1191. WSASetLastError(0);
  1192. }
  1193. if(0 == iResult)
  1194. {
  1195. //
  1196. // Get the size of the first data block from the query
  1197. //
  1198. iResult = WSALookupServiceNext(hLookup, LUP_RETURN_ALL | LUP_FLUSHCACHE, &dwBufLen,
  1199. pBuffer);
  1200. //
  1201. // Allocate the required space for the query data
  1202. //
  1203. pBuffer = (WSAQUERYSET*)malloc(dwBufLen);
  1204. ASSERT(pBuffer != NULL);
  1205. if (pBuffer == NULL)
  1206. {
  1207. return E_OUTOFMEMORY;
  1208. }
  1209. else
  1210. {
  1211. //
  1212. // Get the first data block from the query
  1213. //
  1214. iResult = WSALookupServiceNext(hLookup, LUP_RETURN_ALL | LUP_FLUSHCACHE, &dwBufLen,
  1215. pBuffer);
  1216. //
  1217. // Loop through all the data in the query but stop if we get a valid IP address
  1218. // for the remote machine.
  1219. //
  1220. while(0 == iResult)
  1221. {
  1222. if (pBuffer != NULL &&
  1223. pBuffer->lpcsaBuffer != NULL &&
  1224. pBuffer->lpcsaBuffer->RemoteAddr.lpSockaddr != NULL)
  1225. {
  1226. //
  1227. // We are only interested in the socket address so get a pointer to the sockaddr structure
  1228. //
  1229. sockaddr_in* pSockAddr = (sockaddr_in*)pBuffer->lpcsaBuffer->RemoteAddr.lpSockaddr;
  1230. ASSERT(pSockAddr != NULL);
  1231. //
  1232. // Pull the IP address of the remote machine and pack it into a DWORD
  1233. //
  1234. DWORD dwIP = 0;
  1235. dwIP = pSockAddr->sin_addr.S_un.S_un_b.s_b1;
  1236. dwIP |= pSockAddr->sin_addr.S_un.S_un_b.s_b2 << 8;
  1237. dwIP |= pSockAddr->sin_addr.S_un.S_un_b.s_b3 << 16;
  1238. dwIP |= pSockAddr->sin_addr.S_un.S_un_b.s_b4 << 24;
  1239. //
  1240. // Increment the IP count and allocate space for the address
  1241. //
  1242. (*pnIPCount)++;
  1243. *pipArray = (IP_ADDRESS*)malloc((*pnIPCount)*sizeof(IP_ADDRESS));
  1244. if (*pipArray != NULL)
  1245. {
  1246. //
  1247. // Copy the IP address into the IP array
  1248. //
  1249. PIP_ADDRESS pCurrAddr = *pipArray;
  1250. *pCurrAddr = dwIP;
  1251. }
  1252. //
  1253. // Break since we were able to obtain an IP address
  1254. //
  1255. break;
  1256. }
  1257. //
  1258. // Free the buffer if it is still there
  1259. //
  1260. if (pBuffer != NULL)
  1261. {
  1262. free(pBuffer);
  1263. pBuffer = NULL;
  1264. dwBufLen = 0;
  1265. }
  1266. //
  1267. // Get the size of the next data block from the query
  1268. //
  1269. iResult = WSALookupServiceNext(hLookup, LUP_RETURN_ALL | LUP_FLUSHCACHE, &dwBufLen,
  1270. pBuffer);
  1271. //
  1272. // Allocate enough space for the next data block from the query
  1273. //
  1274. pBuffer = (WSAQUERYSET*)malloc(dwBufLen);
  1275. ASSERT(pBuffer != NULL);
  1276. if (pBuffer)
  1277. {
  1278. //
  1279. // Get the next data block from the query
  1280. //
  1281. iResult = WSALookupServiceNext(hLookup, LUP_RETURN_ALL, &dwBufLen,
  1282. pBuffer);
  1283. }
  1284. else
  1285. {
  1286. // NTRAID#NTBUG9-666458-2002/07/18-JeffJon
  1287. // If the buffer is NULL at this point we have to act like we were
  1288. // unable to obtain an IP address due to memory constraints
  1289. break;
  1290. }
  1291. }
  1292. //
  1293. // Free the buffer if it hasn't already been freed
  1294. //
  1295. if (pBuffer != NULL)
  1296. {
  1297. free(pBuffer);
  1298. pBuffer = NULL;
  1299. }
  1300. }
  1301. //
  1302. // Close the handle to the query
  1303. //
  1304. iResult = WSALookupServiceEnd(hLookup);
  1305. ASSERT(iResult == 0);
  1306. //
  1307. // If we didn't get an IP address return an error
  1308. //
  1309. dwErr = (*pnIPCount < 1) ? -1 : 0;
  1310. }
  1311. }
  1312. return dwErr;
  1313. }
  1314. DNS_STATUS CDNSServerTestTimerThread::DoNothingQuery(PIP_ARRAY pipArr, BOOL bSimple)
  1315. {
  1316. PDNS_RECORD pRecordList = NULL;
  1317. DNS_STATUS dwErr = 0;
  1318. if (bSimple)
  1319. {
  1320. dwErr = ::DnsQuery(_T("1.0.0.127.in-addr.arpa"),
  1321. DNS_TYPE_PTR,
  1322. DNS_QUERY_NO_RECURSION | DNS_QUERY_BYPASS_CACHE | DNS_QUERY_ACCEPT_PARTIAL_UDP | DNS_QUERY_WIRE_ONLY,
  1323. pipArr, &pRecordList, NULL);
  1324. }
  1325. else
  1326. {
  1327. dwErr = ::DnsQuery(_T("."),
  1328. DNS_TYPE_NS,
  1329. DNS_QUERY_STANDARD | DNS_QUERY_BYPASS_CACHE | DNS_QUERY_ACCEPT_PARTIAL_UDP,
  1330. pipArr, &pRecordList, NULL);
  1331. }
  1332. if (pRecordList != NULL)
  1333. ::DnsRecordListFree(pRecordList, DnsFreeRecordListDeep);
  1334. return dwErr;
  1335. }