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.

1849 lines
48 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // DS Administration MMC snapin.
  4. //
  5. // Microsoft Windows
  6. // Copyright (C) Microsoft Corporation, 1992 - 1999
  7. //
  8. // File: DSDlgs.cpp
  9. //
  10. // Contents: TBD
  11. //
  12. // History: 02-Oct-96 WayneSc Created
  13. //
  14. //-----------------------------------------------------------------------------
  15. #include "stdafx.h"
  16. #include "resource.h"
  17. #include "dssnap.h"
  18. #include "uiutil.h"
  19. #include "DSDlgs.h"
  20. #include "helpids.h"
  21. #include "dsrole.h" // DsRoleGetPrimaryDomainInformation
  22. #include <lm.h>
  23. #include <dsgetdc.h>
  24. #ifdef _DEBUG
  25. #define new DEBUG_NEW
  26. #undef THIS_FILE
  27. static char THIS_FILE[] = __FILE__;
  28. #endif
  29. /////////////////////////////////////////////////////////////////////////////
  30. // CChangePassword dialog
  31. CChangePassword::CChangePassword(CWnd* pParent /*=NULL*/)
  32. : CHelpDialog(CChangePassword::IDD, pParent)
  33. {
  34. //{{AFX_DATA_INIT(CChangePassword)
  35. m_ConfirmPwd = _T("");
  36. m_NewPwd = _T("");
  37. m_ChangePwd = FALSE;
  38. //}}AFX_DATA_INIT
  39. m_bAllowMustChangePwdCheck = TRUE;
  40. }
  41. BOOL CChangePassword::OnInitDialog()
  42. {
  43. CHelpDialog::OnInitDialog();
  44. SendDlgItemMessage(IDC_NEW_PASSWORD, EM_LIMITTEXT, (WPARAM)127, 0);
  45. SendDlgItemMessage(IDC_CONFIRM_PASSWORD, EM_LIMITTEXT, (WPARAM)127, 0);
  46. GetDlgItem(IDC_CHECK_PASSWORD_MUST_CHANGE)->EnableWindow(m_bAllowMustChangePwdCheck);
  47. return TRUE;
  48. }
  49. void CChangePassword::DoDataExchange(CDataExchange* pDX)
  50. {
  51. CHelpDialog::DoDataExchange(pDX);
  52. //{{AFX_DATA_MAP(CChangePassword)
  53. DDX_Text(pDX, IDC_CONFIRM_PASSWORD, m_ConfirmPwd);
  54. DDX_Text(pDX, IDC_NEW_PASSWORD, m_NewPwd);
  55. DDX_Check(pDX, IDC_CHECK_PASSWORD_MUST_CHANGE, m_ChangePwd);
  56. //}}AFX_DATA_MAP
  57. }
  58. void CChangePassword::Clear()
  59. {
  60. m_ConfirmPwd = _T("");
  61. m_NewPwd = _T("");
  62. SetDlgItemText(IDC_NEW_PASSWORD, L"");
  63. SetDlgItemText(IDC_CONFIRM_PASSWORD, L"");
  64. }
  65. BEGIN_MESSAGE_MAP(CChangePassword, CHelpDialog)
  66. END_MESSAGE_MAP()
  67. void CChangePassword::DoContextHelp(HWND hWndControl)
  68. {
  69. if (hWndControl)
  70. {
  71. ::WinHelp(hWndControl,
  72. DSADMIN_CONTEXT_HELP_FILE,
  73. HELP_WM_HELP,
  74. (DWORD_PTR)(LPTSTR)g_aHelpIDs_IDD_CHANGE_PASSWORD);
  75. }
  76. }
  77. /////////////////////////////////////////////////////////////////////////////
  78. // Helper functions for CChooseDomainDlg and CChooseDCDlg
  79. //
  80. //+---------------------------------------------------------------------------
  81. //
  82. // Function: BrowseDomainTree
  83. //
  84. // Synopsis: This function invokes IDsBrowseDomainTree::BrowseTo(),
  85. // which brings up the domain tree browse dialog, and returns the
  86. // selected domain's DNS name
  87. //
  88. // NOTE: the OUT parameter needs to be LocalFreeString() by the caller
  89. // NOTE: this function will return S_FALSE if user clicks Cancel button
  90. //
  91. //----------------------------------------------------------------------------
  92. HRESULT BrowseDomainTree(
  93. IN HWND hwndParent,
  94. IN LPCTSTR pszServer,
  95. OUT LPTSTR *ppszDomainDnsName
  96. )
  97. {
  98. ASSERT(ppszDomainDnsName);
  99. ASSERT(!(*ppszDomainDnsName)); // prevent memory leak
  100. *ppszDomainDnsName = NULL;
  101. CComPtr<IDsBrowseDomainTree> spDsDomains;
  102. HRESULT hr = ::CoCreateInstance(CLSID_DsDomainTreeBrowser,
  103. NULL,
  104. CLSCTX_INPROC_SERVER,
  105. IID_IDsBrowseDomainTree,
  106. reinterpret_cast<void **>(&spDsDomains));
  107. if (SUCCEEDED(hr))
  108. {
  109. if (pszServer && *pszServer)
  110. hr = spDsDomains->SetComputer(pszServer, NULL, NULL); // use default credential
  111. if (SUCCEEDED(hr))
  112. {
  113. LPTSTR lpszDomainPath;
  114. hr = spDsDomains->BrowseTo(
  115. hwndParent, //HWND hwndParent
  116. &lpszDomainPath, // LPWSTR *ppszTargetPath
  117. DBDTF_RETURNINBOUND);
  118. if ( (hr == S_OK) && lpszDomainPath)
  119. {
  120. *ppszDomainDnsName = lpszDomainPath; //should be freed by CoTaskMemFree later
  121. }
  122. }
  123. }
  124. return hr;
  125. }
  126. HRESULT GetDCOfDomain(
  127. IN CString& csDomainName,
  128. OUT CString& csDCName,
  129. IN BOOL bForce
  130. )
  131. {
  132. ASSERT(csDomainName.IsEmpty() == FALSE);
  133. CString csServerName;
  134. DWORD dwErr = 0;
  135. csDCName.Empty();
  136. PDOMAIN_CONTROLLER_INFO pDCInfo = NULL;
  137. if (bForce)
  138. dwErr = DsGetDcName(NULL, csDomainName, NULL, NULL,
  139. DS_DIRECTORY_SERVICE_PREFERRED | DS_FORCE_REDISCOVERY, &pDCInfo);
  140. else
  141. dwErr = DsGetDcName(NULL, csDomainName, NULL, NULL,
  142. DS_DIRECTORY_SERVICE_PREFERRED, &pDCInfo);
  143. if (ERROR_SUCCESS == dwErr)
  144. {
  145. if ( !(pDCInfo->Flags & DS_DS_FLAG) )
  146. {
  147. // down level domain
  148. NetApiBufferFree(pDCInfo);
  149. return S_OK;
  150. }
  151. csDCName = pDCInfo->DomainControllerName;
  152. NetApiBufferFree(pDCInfo);
  153. }
  154. return HRESULT_FROM_WIN32(dwErr);
  155. }
  156. //+---------------------------------------------------------------------------
  157. //
  158. // Function: GetDnsNameOfDomainOrForest
  159. //
  160. // Synopsis: Given a server name or a domain name (either NETBIOS or DNS),
  161. // this function will return the DNS name for its domain or forest.
  162. //
  163. // Parameters:
  164. // csName, // a server name or a domain name
  165. // csDnsName, // hold the returning DNS name
  166. // bIsInputADomainName, // TRUE if csName is a domain name, FALSE if it's a server name
  167. // bRequireDomain // TRUE for a domain dns name, FALSE for a forest dns name
  168. //
  169. //----------------------------------------------------------------------------
  170. HRESULT GetDnsNameOfDomainOrForest(
  171. IN CString& csName,
  172. OUT CString& csDnsName,
  173. IN BOOL bIsInputADomainName,
  174. IN BOOL bRequireDomain
  175. )
  176. {
  177. BOOL bRetry = FALSE;
  178. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pBuffer = NULL;
  179. CString csServerName;
  180. DWORD dwErr = 0;
  181. csDnsName.Empty();
  182. do {
  183. if (bIsInputADomainName)
  184. {
  185. PDOMAIN_CONTROLLER_INFO pDCInfo = NULL;
  186. if (bRetry)
  187. dwErr = DsGetDcName(NULL, csName, NULL, NULL,
  188. DS_DIRECTORY_SERVICE_PREFERRED | DS_FORCE_REDISCOVERY, &pDCInfo);
  189. else
  190. dwErr = DsGetDcName(NULL, csName, NULL, NULL,
  191. DS_DIRECTORY_SERVICE_PREFERRED, &pDCInfo);
  192. if (ERROR_SUCCESS == dwErr)
  193. {
  194. if ( !(pDCInfo->Flags & DS_DS_FLAG) )
  195. {
  196. // down level domain
  197. NetApiBufferFree(pDCInfo);
  198. return S_OK;
  199. }
  200. DWORD dwExpectFlag = (bRequireDomain ?
  201. DS_DNS_DOMAIN_FLAG :
  202. DS_DNS_FOREST_FLAG);
  203. if (pDCInfo->Flags & dwExpectFlag)
  204. {
  205. // skip call to DsRoleGetPrimaryDomainInformation()
  206. csDnsName = (bRequireDomain ?
  207. pDCInfo->DomainName :
  208. pDCInfo->DnsForestName);
  209. NetApiBufferFree(pDCInfo);
  210. //
  211. // The DNS name is in absolute form, remove the ending dot
  212. //
  213. if (csDnsName.Right(1) == _T("."))
  214. csDnsName.SetAt(csDnsName.GetLength() - 1, _T('\0'));
  215. return S_OK;
  216. } else {
  217. csServerName = pDCInfo->DomainControllerName;
  218. NetApiBufferFree(pDCInfo);
  219. }
  220. } else
  221. {
  222. return HRESULT_FROM_WIN32(dwErr);
  223. }
  224. } else
  225. {
  226. csServerName = csName;
  227. }
  228. dwErr = DsRoleGetPrimaryDomainInformation(
  229. csServerName,
  230. DsRolePrimaryDomainInfoBasic,
  231. (PBYTE *)&pBuffer);
  232. if (RPC_S_SERVER_UNAVAILABLE == dwErr && bIsInputADomainName && !bRetry)
  233. bRetry = TRUE; // only retry once
  234. else
  235. break;
  236. } while (1);
  237. if (ERROR_SUCCESS == dwErr)
  238. {
  239. csDnsName = (bRequireDomain ?
  240. pBuffer->DomainNameDns :
  241. pBuffer->DomainForestName);
  242. if (csDnsName.IsEmpty())
  243. {
  244. if (pBuffer->Flags & DSROLE_PRIMARY_DS_RUNNING)
  245. csDnsName = pBuffer->DomainNameFlat;
  246. }
  247. DsRoleFreeMemory(pBuffer);
  248. //
  249. // In case the DNS name is in absolute form, remove the ending dot
  250. //
  251. if (csDnsName.Right(1) == _T("."))
  252. csDnsName.SetAt(csDnsName.GetLength() - 1, _T('\0'));
  253. }
  254. return HRESULT_FROM_WIN32(dwErr);
  255. }
  256. /////////////////////////////////////////////////////////////////////////////
  257. // CChooseDomainDlg dialog
  258. CChooseDomainDlg::CChooseDomainDlg(CWnd* pParent /*=NULL*/)
  259. : CHelpDialog(CChooseDomainDlg::IDD, pParent)
  260. {
  261. //{{AFX_DATA_INIT(CChooseDomainDlg)
  262. m_csTargetDomain = _T("");
  263. m_bSaveCurrent = FALSE;
  264. //}}AFX_DATA_INIT
  265. }
  266. void CChooseDomainDlg::DoDataExchange(CDataExchange* pDX)
  267. {
  268. CHelpDialog::DoDataExchange(pDX);
  269. //{{AFX_DATA_MAP(CChooseDomainDlg)
  270. DDX_Text(pDX, IDC_SELECTDOMAIN_DOMAIN, m_csTargetDomain);
  271. DDX_Check(pDX, IDC_SAVE_CURRENT_CHECK, m_bSaveCurrent);
  272. //}}AFX_DATA_MAP
  273. }
  274. BEGIN_MESSAGE_MAP(CChooseDomainDlg, CHelpDialog)
  275. //{{AFX_MSG_MAP(CChooseDomainDlg)
  276. ON_BN_CLICKED(IDC_SELECTDOMAIN_BROWSE, OnSelectdomainBrowse)
  277. //}}AFX_MSG_MAP
  278. END_MESSAGE_MAP()
  279. /////////////////////////////////////////////////////////////////////////////
  280. // CChooseDomainDlg message handlers
  281. void CChooseDomainDlg::OnSelectdomainBrowse()
  282. {
  283. CWaitCursor cwait;
  284. HRESULT hr = S_OK;
  285. LPTSTR lpszDomainDnsName = NULL;
  286. CString csDomainName, csDCName;
  287. GetDlgItemText(IDC_SELECTDOMAIN_DOMAIN, csDomainName);
  288. csDomainName.TrimLeft();
  289. csDomainName.TrimRight();
  290. if (!csDomainName.IsEmpty())
  291. hr = GetDCOfDomain(csDomainName, csDCName, FALSE);
  292. if (SUCCEEDED(hr))
  293. {
  294. hr = BrowseDomainTree(m_hWnd, csDCName, &lpszDomainDnsName);
  295. if ( FAILED(hr) &&
  296. !csDCName.IsEmpty() &&
  297. HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) == hr )
  298. {
  299. // force the cached info in DsGetDcName to be refreshed
  300. hr = GetDCOfDomain(csDomainName, csDCName, TRUE);
  301. if (SUCCEEDED(hr))
  302. hr = BrowseDomainTree(m_hWnd, csDCName, &lpszDomainDnsName);
  303. }
  304. if ( (hr == S_OK) && lpszDomainDnsName )
  305. {
  306. SetDlgItemText(IDC_SELECTDOMAIN_DOMAIN, lpszDomainDnsName);
  307. CoTaskMemFree(lpszDomainDnsName);
  308. }
  309. }
  310. if (FAILED(hr)) {
  311. PVOID apv[1];
  312. apv[0] = static_cast<PVOID>(const_cast<LPTSTR>(static_cast<LPCTSTR>(csDomainName)));
  313. ReportErrorEx(m_hWnd,IDS_CANT_BROWSE_DOMAIN, hr,
  314. MB_OK | MB_ICONERROR, apv, 1, 0);
  315. }
  316. GetDlgItem(IDC_SELECTDOMAIN_DOMAIN)->SetFocus();
  317. }
  318. void CChooseDomainDlg::OnOK()
  319. {
  320. CWaitCursor cwait;
  321. HRESULT hr = S_OK;
  322. CString csName, csDnsName;
  323. //
  324. // Validate contents in the domain edit box
  325. //
  326. GetDlgItemText(IDC_SELECTDOMAIN_DOMAIN, csName);
  327. if (csName.IsEmpty())
  328. {
  329. ReportMessageEx(m_hWnd, IDS_INCORRECT_INPUT,
  330. MB_OK | MB_ICONSTOP);
  331. (GetDlgItem(IDC_SELECTDOMAIN_DOMAIN))->SetFocus();
  332. return;
  333. }
  334. hr = GetDnsNameOfDomainOrForest(
  335. csName,
  336. csDnsName,
  337. TRUE,
  338. !m_bSiteRepl);
  339. if (csDnsName.IsEmpty())
  340. {
  341. PVOID apv[1];
  342. apv[0] = static_cast<PVOID>(const_cast<LPTSTR>(static_cast<LPCTSTR>(csName)));
  343. if (FAILED(hr))
  344. ReportErrorEx(m_hWnd, IDS_SELECTDOMAIN_INCORRECT_DOMAIN_DUETO, hr,
  345. MB_OK | MB_ICONSTOP, apv, 1, 0);
  346. else
  347. ReportMessageEx(m_hWnd, IDS_SELECTDOMAIN_DOWNLEVEL_DOMAIN,
  348. MB_OK | MB_ICONSTOP, apv, 1);
  349. SetDlgItemText(IDC_SELECTDOMAIN_DOMAIN, _T(""));
  350. (GetDlgItem (IDC_SELECTDOMAIN_DOMAIN))->SetFocus();
  351. return;
  352. }
  353. //
  354. // When exiting from the dialog
  355. // use DNS domain name;
  356. //
  357. SetDlgItemText(IDC_SELECTDOMAIN_DOMAIN, csDnsName);
  358. CHelpDialog::OnOK();
  359. }
  360. BOOL CChooseDomainDlg::OnInitDialog()
  361. {
  362. CHelpDialog::OnInitDialog();
  363. //
  364. // for siterepl snapin only,
  365. // change dialog title to "Choose Target Forest"
  366. // change domain label to "Root domain:"
  367. // hide browse button
  368. //
  369. if (m_bSiteRepl)
  370. {
  371. CString csDlgTitle, csLabel;
  372. csDlgTitle.LoadString(IDS_SELECTDOMAIN_TITLE_FOREST);
  373. SetWindowText(csDlgTitle);
  374. csLabel.LoadString(IDS_SELECTDOMAIN_DOMAIN_LABEL);
  375. SetDlgItemText(IDC_SELECTDOMAIN_LABEL, csLabel);
  376. // Hide & Disable the Browse button for SiteRepl snapin
  377. (GetDlgItem(IDC_SELECTDOMAIN_BROWSE))->ShowWindow(SW_HIDE);
  378. (GetDlgItem(IDC_SELECTDOMAIN_BROWSE))->EnableWindow(FALSE);
  379. }
  380. return TRUE; // return TRUE unless you set the focus to a control
  381. // EXCEPTION: OCX Property Pages should return FALSE
  382. }
  383. void CChooseDomainDlg::DoContextHelp(HWND hWndControl)
  384. {
  385. if (hWndControl)
  386. {
  387. ::WinHelp(hWndControl,
  388. DSADMIN_CONTEXT_HELP_FILE,
  389. HELP_WM_HELP,
  390. (DWORD_PTR)(LPTSTR)g_aHelpIDs_IDD_SELECT_DOMAIN);
  391. }
  392. }
  393. /////////////////////////////////////////////////////////////////////////////
  394. // CChooseDCDlg dialog
  395. BEGIN_MESSAGE_MAP(CSelectDCEdit, CEdit)
  396. ON_WM_KILLFOCUS()
  397. END_MESSAGE_MAP()
  398. void CSelectDCEdit::OnKillFocus(CWnd* pNewWnd)
  399. {
  400. //
  401. // subclass the domain edit control.
  402. // When focus moves to OK/Cancel/Browse button, do not invoke
  403. // RefreshDCListView
  404. //
  405. m_bHandleKillFocus = TRUE;
  406. if (pNewWnd)
  407. {
  408. int id = pNewWnd->GetDlgCtrlID();
  409. if (id == IDOK ||
  410. id == IDCANCEL ||
  411. id == IDC_SELECTDC_BROWSE)
  412. {
  413. m_bHandleKillFocus = FALSE;
  414. }
  415. }
  416. CEdit::OnKillFocus(pNewWnd);
  417. }
  418. CChooseDCDlg::CChooseDCDlg(CWnd* pParent /*=NULL*/)
  419. : CHelpDialog(CChooseDCDlg::IDD, pParent)
  420. {
  421. //{{AFX_DATA_INIT(CChooseDCDlg)
  422. m_csTargetDomainController = _T("");
  423. m_csTargetDomain = _T("");
  424. //}}AFX_DATA_INIT
  425. m_csPrevDomain = _T("");
  426. m_pDCBufferManager = NULL;
  427. m_csAnyDC.LoadString(IDS_ANY_DOMAIN_CONTROLLER);
  428. m_csWaiting.LoadString(IDS_WAITING);
  429. m_csError.LoadString(IDS_ERROR);
  430. }
  431. CChooseDCDlg::~CChooseDCDlg()
  432. {
  433. TRACE(_T("CChooseDCDlg::~CChooseDCDlg\n"));
  434. if (m_pDCBufferManager)
  435. {
  436. //
  437. // signal all related running threads to terminate
  438. //
  439. m_pDCBufferManager->SignalExit();
  440. //
  441. // decrement the reference count on the CDCBufferManager instance
  442. //
  443. m_pDCBufferManager->Release();
  444. }
  445. CHelpDialog::~CHelpDialog();
  446. }
  447. void CChooseDCDlg::DoDataExchange(CDataExchange* pDX)
  448. {
  449. CHelpDialog::DoDataExchange(pDX);
  450. //{{AFX_DATA_MAP(CChooseDCDlg)
  451. DDX_Control(pDX, IDC_SELECTDC_DCLISTVIEW, m_hDCListView);
  452. DDX_Text(pDX, IDC_SELECTDC_DCEDIT, m_csTargetDomainController);
  453. DDX_Text(pDX, IDC_SELECTDC_DOMAIN, m_csTargetDomain);
  454. //}}AFX_DATA_MAP
  455. }
  456. BEGIN_MESSAGE_MAP(CChooseDCDlg, CHelpDialog)
  457. //{{AFX_MSG_MAP(CChooseDCDlg)
  458. ON_NOTIFY(LVN_ITEMCHANGED, IDC_SELECTDC_DCLISTVIEW, OnItemchangedSelectdcDCListView)
  459. ON_EN_KILLFOCUS(IDC_SELECTDC_DOMAIN, OnKillfocusSelectdcDomain)
  460. ON_BN_CLICKED(IDC_SELECTDC_BROWSE, OnSelectdcBrowse)
  461. ON_NOTIFY(LVN_COLUMNCLICK, IDC_SELECTDC_DCLISTVIEW, OnColumnclickSelectdcDCListView)
  462. //}}AFX_MSG_MAP
  463. ON_MESSAGE(WM_USER_GETDC_THREAD_DONE, OnGetDCThreadDone)
  464. END_MESSAGE_MAP()
  465. /////////////////////////////////////////////////////////////////////////////
  466. // CChooseDCDlg message handlers
  467. typedef struct _DCListViewItem
  468. {
  469. CString csName;
  470. CString csSite;
  471. } DCLISTVIEWITEM;
  472. BOOL CChooseDCDlg::OnInitDialog()
  473. {
  474. CHelpDialog::OnInitDialog();
  475. //
  476. // sub-class the domain edit control, in order to intercept WM_KILLFOCUS
  477. // if the new focus will be set on Cancel button, don't process
  478. // EN_KILLFOCUS (i.e., don't start the thread to refresh DC list view )
  479. //
  480. VERIFY(m_selectDCEdit.SubclassDlgItem(IDC_SELECTDC_DOMAIN, this));
  481. //
  482. // create instance of CDCBufferManager
  483. // m_pDCBufferManager will be set to NULL if CreateInstance() failed.
  484. //
  485. (void) CDCBufferManager::CreateInstance(m_hWnd, &m_pDCBufferManager);
  486. //
  487. // display currently targeted domain controller
  488. //
  489. CString csText, csFormat;
  490. csFormat.LoadString(IDS_SELECTDC_DCEDIT_TITLE);
  491. csText.Format(csFormat, m_csTargetDomainController);
  492. SetDlgItemText(IDC_SELECTDC_DCEDIT_TITLE, csText);
  493. //
  494. // calculate the listview column width
  495. //
  496. RECT rect;
  497. ZeroMemory(&rect, sizeof(rect));
  498. (GetDlgItem(IDC_SELECTDC_DCLISTVIEW))->GetWindowRect(&rect);
  499. int nControlWidth = rect.right - rect.left;
  500. int nVScrollbarWidth = GetSystemMetrics(SM_CXVSCROLL);
  501. int nBorderWidth = GetSystemMetrics(SM_CXBORDER);
  502. int nControlNetWidth = nControlWidth - nVScrollbarWidth - 4 * nBorderWidth;
  503. int nWidth1 = nControlNetWidth / 2;
  504. int nWidth2 = nControlNetWidth - nWidth1;
  505. //
  506. // insert two columns of DC list view
  507. //
  508. LV_COLUMN col;
  509. CString cstrText;
  510. ZeroMemory(&col, sizeof(col));
  511. col.mask = LVCF_TEXT | LVCF_WIDTH;
  512. col.cx = nWidth1;
  513. cstrText.LoadString(IDS_SELECTDC_DCLISTVIEW_NAME);
  514. col.pszText = const_cast<LPTSTR>(static_cast<LPCTSTR>(cstrText));
  515. ListView_InsertColumn(m_hDCListView, 0, &col);
  516. col.cx = nWidth2;
  517. cstrText.LoadString(IDS_SELECTDC_DCLISTVIEW_SITE);
  518. col.pszText = const_cast<LPTSTR>(static_cast<LPCTSTR>(cstrText));
  519. ListView_InsertColumn(m_hDCListView, 1, &col);
  520. //
  521. // Set full row selection style
  522. //
  523. ListView_SetExtendedListViewStyleEx(m_hDCListView, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
  524. //
  525. // disable the list view control
  526. // In case we failed to create a CDCBufferManager instance, user can
  527. // still use this dialog to type in a domain name and a DC name.
  528. //
  529. m_hDCListView.EnableWindow(FALSE);
  530. //
  531. // insert items into DC list view
  532. //
  533. RefreshDCListView();
  534. if (!m_bSiteRepl)
  535. {
  536. //
  537. // Disable domain edit box and hide&disable Browse button for non-siterepl snapins
  538. //
  539. (reinterpret_cast<CEdit *>(GetDlgItem(IDC_SELECTDC_DOMAIN)))->SetReadOnly(TRUE);
  540. (GetDlgItem(IDC_SELECTDC_BROWSE))->ShowWindow(SW_HIDE);
  541. (GetDlgItem(IDC_SELECTDC_BROWSE))->EnableWindow(FALSE);
  542. //
  543. // for non-siterepl snapins, set focus to the DC edit box;
  544. // for siterepl snapin, the focus will be set on the domain edit box.
  545. //
  546. (GetDlgItem(IDC_SELECTDC_DCEDIT))->SetFocus();
  547. return FALSE;
  548. }
  549. return TRUE;
  550. // return TRUE unless you set the focus to a control
  551. // EXCEPTION: OCX Property Pages should return FALSE
  552. }
  553. int CALLBACK ListViewCompareProc(
  554. IN LPARAM lParam1,
  555. IN LPARAM lParam2,
  556. IN LPARAM lParamSort)
  557. {
  558. DCLISTVIEWITEM *pItem1 = (DCLISTVIEWITEM *)lParam1;
  559. DCLISTVIEWITEM *pItem2 = (DCLISTVIEWITEM *)lParam2;
  560. int iResult = 0;
  561. if (pItem1 && pItem2)
  562. {
  563. switch( lParamSort)
  564. {
  565. case 0: // Sort by Name.
  566. iResult = pItem1->csName.CompareNoCase(pItem2->csName);
  567. break;
  568. case 1: // Sort by Site.
  569. iResult = pItem1->csSite.CompareNoCase(pItem2->csSite);
  570. break;
  571. default:
  572. iResult = 0;
  573. break;
  574. }
  575. }
  576. return(iResult);
  577. }
  578. void CChooseDCDlg::OnColumnclickSelectdcDCListView(NMHDR* pNMHDR, LRESULT* pResult)
  579. {
  580. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  581. ListView_SortItems( m_hDCListView,
  582. ListViewCompareProc,
  583. (LPARAM)(pNMListView->iSubItem));
  584. *pResult = 0;
  585. }
  586. #define MAX_LENGTH_DCNAME 1024
  587. void CChooseDCDlg::OnItemchangedSelectdcDCListView(NMHDR* pNMHDR, LRESULT* pResult)
  588. {
  589. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  590. //
  591. // set DC edit box to the currently selected item in the dc list view
  592. //
  593. if ( (pNMListView->uChanged & LVIF_STATE) &&
  594. (pNMListView->uNewState & LVIS_SELECTED) )
  595. {
  596. TCHAR pszBuffer[MAX_LENGTH_DCNAME];
  597. ListView_GetItemText(
  598. (GetDlgItem(IDC_SELECTDC_DCLISTVIEW))->GetSafeHwnd(),
  599. pNMListView->iItem,
  600. 0,
  601. pszBuffer,
  602. MAX_LENGTH_DCNAME * sizeof(TCHAR)
  603. );
  604. SetDlgItemText(IDC_SELECTDC_DCEDIT, pszBuffer);
  605. }
  606. *pResult = 0;
  607. }
  608. void CChooseDCDlg::OnKillfocusSelectdcDomain()
  609. {
  610. TRACE(_T("CChooseDCDlg::OnKillfocusSelectdcDomain\n"));
  611. //
  612. // when focus leaves domain edit box, refresh the items in the dc list view
  613. // we do this only for siterepl snapin whose domain edit box is enabled.
  614. //
  615. if (m_selectDCEdit.m_bHandleKillFocus)
  616. {
  617. if (m_bSiteRepl)
  618. RefreshDCListView();
  619. }
  620. }
  621. void CChooseDCDlg::OnSelectdcBrowse()
  622. {
  623. CWaitCursor cwait;
  624. //
  625. // bring up the domain tree browse dialog
  626. //
  627. HRESULT hr = S_OK;
  628. LPTSTR lpszDomainDnsName = NULL;
  629. CString csDomainName, csDCName;
  630. GetDlgItemText(IDC_SELECTDC_DOMAIN, csDomainName);
  631. csDomainName.TrimLeft();
  632. csDomainName.TrimRight();
  633. if (!csDomainName.IsEmpty())
  634. hr = GetDCOfDomain(csDomainName, csDCName, FALSE);
  635. if (SUCCEEDED(hr))
  636. {
  637. hr = BrowseDomainTree(m_hWnd, csDCName, &lpszDomainDnsName);
  638. if ( FAILED(hr) &&
  639. !csDCName.IsEmpty() &&
  640. HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) == hr )
  641. {
  642. // force the cached info in DsGetDcName to be refreshed
  643. hr = GetDCOfDomain(csDomainName, csDCName, TRUE);
  644. if (SUCCEEDED(hr))
  645. hr = BrowseDomainTree(m_hWnd, csDCName, &lpszDomainDnsName);
  646. }
  647. if ( (hr == S_OK) && lpszDomainDnsName )
  648. {
  649. SetDlgItemText(IDC_SELECTDC_DOMAIN, lpszDomainDnsName);
  650. CoTaskMemFree(lpszDomainDnsName);
  651. RefreshDCListView();
  652. }
  653. }
  654. if (FAILED(hr)) {
  655. PVOID apv[1];
  656. apv[0] = static_cast<PVOID>(const_cast<LPTSTR>(static_cast<LPCTSTR>(csDomainName)));
  657. ReportErrorEx(m_hWnd,IDS_CANT_BROWSE_DOMAIN, hr,
  658. MB_OK | MB_ICONERROR, apv, 1, 0);
  659. }
  660. GetDlgItem(IDC_SELECTDC_DOMAIN)->SetFocus();
  661. }
  662. void CChooseDCDlg::OnOK()
  663. {
  664. TRACE(_T("CChooseDCDlg::OnOK\n"));
  665. CWaitCursor wait;
  666. HRESULT hr = S_OK;
  667. CString csDnsForSelectedDomain;
  668. CString csDnsForCurrentForest, csDnsForSelectedForest;
  669. if (m_bSiteRepl)
  670. {
  671. hr = GetDnsNameOfDomainOrForest(
  672. m_csTargetDomain,
  673. csDnsForCurrentForest,
  674. TRUE,
  675. FALSE); // get forest name
  676. if (csDnsForCurrentForest.IsEmpty())
  677. csDnsForCurrentForest = m_csTargetDomain;
  678. }
  679. //
  680. // Validate contents in the DC edit box
  681. //
  682. CString csDCEdit;
  683. GetDlgItemText(IDC_SELECTDC_DCEDIT, csDCEdit);
  684. // treat empty csDCEdit as same as m_csAnyDC
  685. if (!csDCEdit.IsEmpty() && m_csAnyDC.CompareNoCase(csDCEdit))
  686. {
  687. hr = GetDnsNameOfDomainOrForest(
  688. csDCEdit,
  689. csDnsForSelectedDomain,
  690. FALSE,
  691. TRUE); // get domain name
  692. if (SUCCEEDED(hr) && m_bSiteRepl)
  693. {
  694. hr = GetDnsNameOfDomainOrForest(
  695. csDCEdit,
  696. csDnsForSelectedForest,
  697. FALSE,
  698. FALSE); // get forest name
  699. }
  700. if (csDnsForSelectedDomain.IsEmpty() || (m_bSiteRepl && csDnsForSelectedForest.IsEmpty()) )
  701. {
  702. PVOID apv[1];
  703. apv[0] = static_cast<PVOID>(const_cast<LPTSTR>(static_cast<LPCTSTR>(csDCEdit)));
  704. if (FAILED(hr))
  705. ReportErrorEx(m_hWnd, IDS_SELECTDC_INCORRECT_DC_DUETO, hr,
  706. MB_OK | MB_ICONSTOP, apv, 1, 0);
  707. else
  708. ReportMessageEx(m_hWnd, IDS_SELECTDC_DOWNLEVEL_DC,
  709. MB_OK | MB_ICONSTOP, apv, 1);
  710. (GetDlgItem(IDC_SELECTDC_DCEDIT))->SetFocus();
  711. return;
  712. }
  713. } else
  714. {
  715. //
  716. // Validate contents in the domain edit box
  717. //
  718. CString csDomain;
  719. GetDlgItemText(IDC_SELECTDC_DOMAIN, csDomain);
  720. if (csDomain.IsEmpty())
  721. {
  722. ReportMessageEx(m_hWnd, IDS_INCORRECT_INPUT,
  723. MB_OK | MB_ICONSTOP);
  724. (GetDlgItem(IDC_SELECTDC_DOMAIN))->SetFocus();
  725. return;
  726. }
  727. hr = GetDnsNameOfDomainOrForest(
  728. csDomain,
  729. csDnsForSelectedDomain,
  730. TRUE,
  731. TRUE); // get domain name
  732. if (SUCCEEDED(hr) && m_bSiteRepl)
  733. {
  734. hr = GetDnsNameOfDomainOrForest(
  735. csDomain,
  736. csDnsForSelectedForest,
  737. TRUE,
  738. FALSE); // get forest name
  739. }
  740. if (csDnsForSelectedDomain.IsEmpty() || (m_bSiteRepl && csDnsForSelectedForest.IsEmpty()) )
  741. {
  742. PVOID apv[1];
  743. apv[0] = static_cast<PVOID>(const_cast<LPTSTR>(static_cast<LPCTSTR>(csDomain)));
  744. if (FAILED(hr))
  745. ReportErrorEx(m_hWnd, IDS_SELECTDC_INCORRECT_DOMAIN_DUETO, hr,
  746. MB_OK | MB_ICONSTOP, apv, 1, 0);
  747. else
  748. ReportMessageEx(m_hWnd, IDS_SELECTDC_DOWNLEVEL_DOMAIN,
  749. MB_OK | MB_ICONSTOP, apv, 1);
  750. SetDlgItemText(IDC_SELECTDC_DOMAIN, _T(""));
  751. (GetDlgItem(IDC_SELECTDC_DOMAIN))->SetFocus();
  752. return;
  753. }
  754. }
  755. //
  756. // if the current selected forest/domain does not belong to the current administering forest/domain,
  757. // ask user if he really wants to administer the selected forest/domain
  758. // via the selected DC (or any writable DC)?
  759. //
  760. if ( (m_bSiteRepl && csDnsForSelectedForest.CompareNoCase(csDnsForCurrentForest)) ||
  761. (!m_bSiteRepl && csDnsForSelectedDomain.CompareNoCase(m_csTargetDomain)) )
  762. {
  763. int nArgs = 0;
  764. int id = 0;
  765. PVOID apv[3];
  766. apv[0] = static_cast<PVOID>(const_cast<LPTSTR>(static_cast<LPCTSTR>(m_bSiteRepl ? csDnsForCurrentForest : m_csTargetDomain)));
  767. apv[1] = static_cast<PVOID>(const_cast<LPTSTR>(static_cast<LPCTSTR>(m_bSiteRepl ? csDnsForSelectedForest : csDnsForSelectedDomain)));
  768. if (m_csAnyDC.CompareNoCase(csDCEdit))
  769. {
  770. nArgs = 3;
  771. apv[2] = static_cast<PVOID>(const_cast<LPTSTR>(static_cast<LPCTSTR>(csDCEdit)));
  772. id = (m_bSiteRepl ?
  773. IDS_SELECTDC_UNMATCHED_DC_DOMAIN_SITEREPL :
  774. IDS_SELECTDC_UNMATCHED_DC_DOMAIN);
  775. } else
  776. {
  777. nArgs = 2;
  778. id = (m_bSiteRepl ?
  779. IDS_SELECTDC_UNMATCHED_DC_DOMAIN_SITEREPL_ANY :
  780. IDS_SELECTDC_UNMATCHED_DC_DOMAIN_ANY);
  781. }
  782. if (IDYES != ReportMessageEx(m_hWnd, id, MB_YESNO, apv, nArgs))
  783. {
  784. (GetDlgItem(IDC_SELECTDC_DCEDIT))->SetFocus();
  785. return;
  786. }
  787. }
  788. //
  789. // When exiting from the dialog
  790. // use DNS domain name;
  791. // use blank string if "Any Writable DC"
  792. // clean list view control
  793. //
  794. SetDlgItemText(IDC_SELECTDC_DOMAIN, csDnsForSelectedDomain);
  795. if (0 == m_csAnyDC.CompareNoCase(csDCEdit))
  796. SetDlgItemText(IDC_SELECTDC_DCEDIT, _T(""));
  797. FreeDCItems(m_hDCListView);
  798. CHelpDialog::OnOK();
  799. }
  800. void CChooseDCDlg::OnCancel()
  801. {
  802. TRACE(_T("CChooseDCDlg::OnCancel\n"));
  803. //
  804. // When exiting from the dialog
  805. // clean list view control
  806. //
  807. FreeDCItems(m_hDCListView);
  808. CHelpDialog::OnCancel();
  809. }
  810. //+---------------------------------------------------------------------------
  811. //
  812. // Function: CChooseDCDlg::InsertSpecialMsg
  813. //
  814. // Synopsis: Insert "Waiting..." or "Error" into the list view control,
  815. // and disable the control to prevent it from being selected.
  816. //
  817. //----------------------------------------------------------------------------
  818. void
  819. CChooseDCDlg::InsertSpecialMsg(
  820. IN BOOL bWaiting
  821. )
  822. {
  823. LV_ITEM item;
  824. //
  825. // clear DC list view
  826. //
  827. FreeDCItems(m_hDCListView);
  828. ZeroMemory(&item, sizeof(item));
  829. item.mask = LVIF_TEXT;
  830. item.pszText = const_cast<LPTSTR>(
  831. static_cast<LPCTSTR>(bWaiting ? m_csWaiting: m_csError));
  832. ListView_InsertItem(m_hDCListView, &item);
  833. //
  834. // disable the list view to prevent user from clicking on "Waiting..."
  835. //
  836. m_hDCListView.EnableWindow(FALSE);
  837. }
  838. //+---------------------------------------------------------------------------
  839. //
  840. // Function: CChooseDCDlg::InsertDCListView
  841. //
  842. // Synopsis: Insert items into the list view control of the owner dialog.
  843. //
  844. //----------------------------------------------------------------------------
  845. HRESULT
  846. CChooseDCDlg::InsertDCListView(
  847. IN CDCSITEINFO *pEntry
  848. )
  849. {
  850. ASSERT(pEntry);
  851. DWORD cInfo = pEntry->GetNumOfInfo();
  852. PDS_DOMAIN_CONTROLLER_INFO_1 pDCInfo = pEntry->GetDCInfo();
  853. ASSERT(cInfo > 0);
  854. ASSERT(pDCInfo);
  855. LV_ITEM item;
  856. int index = 0;
  857. DCLISTVIEWITEM *pItem = NULL;
  858. DWORD dwErr = 0;
  859. //
  860. // clear DC list view
  861. //
  862. FreeDCItems(m_hDCListView);
  863. //
  864. // insert DC list view
  865. //
  866. ZeroMemory(&item, sizeof(item));
  867. item.mask = LVIF_TEXT | LVIF_PARAM;
  868. for (DWORD i=0; i<cInfo; i++) {
  869. ASSERT(pDCInfo[i].NetbiosName || pDCInfo[i].DnsHostName);
  870. if (pDCInfo[i].DnsHostName)
  871. item.pszText = pDCInfo[i].DnsHostName;
  872. else
  873. item.pszText = pDCInfo[i].NetbiosName;
  874. pItem = new DCLISTVIEWITEM;
  875. if (!pItem)
  876. {
  877. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  878. break;
  879. }
  880. pItem->csName = item.pszText;
  881. if (pDCInfo[i].SiteName)
  882. pItem->csSite = pDCInfo[i].SiteName;
  883. else
  884. pItem->csSite = _T("");
  885. item.lParam = reinterpret_cast<LPARAM>(pItem);
  886. index = ListView_InsertItem(m_hDCListView, &item);
  887. ListView_SetItemText(m_hDCListView, index, 1,
  888. const_cast<LPTSTR>(static_cast<LPCTSTR>(pItem->csSite)));
  889. }
  890. if (ERROR_NOT_ENOUGH_MEMORY != dwErr)
  891. {
  892. // add "All writable domain controllers" into the list-view .
  893. item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
  894. item.pszText = const_cast<LPTSTR>(static_cast<LPCTSTR>(m_csAnyDC));
  895. item.state = LVIS_FOCUSED | LVIS_SELECTED;
  896. pItem = new DCLISTVIEWITEM;
  897. if (!pItem)
  898. {
  899. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  900. } else
  901. {
  902. pItem->csName = _T(""); // always sorted as the top item
  903. pItem->csSite = _T("");
  904. item.lParam = reinterpret_cast<LPARAM>(pItem);
  905. index = ListView_InsertItem(m_hDCListView, &item);
  906. ListView_SetItemText(m_hDCListView, index, 1,
  907. const_cast<LPTSTR>(static_cast<LPCTSTR>(pItem->csSite)));
  908. }
  909. }
  910. if (ERROR_NOT_ENOUGH_MEMORY == dwErr)
  911. {
  912. FreeDCItems(m_hDCListView);
  913. return E_OUTOFMEMORY;
  914. }
  915. m_hDCListView.EnableWindow(TRUE);
  916. return S_OK;
  917. }
  918. void CChooseDCDlg::OnGetDCThreadDone(WPARAM wParam, LPARAM lParam)
  919. {
  920. ASSERT(m_pDCBufferManager);
  921. CDCSITEINFO* pEntry = reinterpret_cast<CDCSITEINFO*>(wParam);
  922. HRESULT hr = (HRESULT)lParam;
  923. ASSERT(pEntry);
  924. CString csDomain = pEntry->GetDomainName();
  925. CString csCurrentDomain;
  926. GetDlgItemText(IDC_SELECTDC_DOMAIN, csCurrentDomain);
  927. TRACE(_T("CChooseDCDlg::OnGetDCThreadDone targetDomain=%s, currentDomain=%s, hr=%x\n"),
  928. csDomain, csCurrentDomain, hr);
  929. if (csCurrentDomain.CompareNoCase(csDomain) == 0)
  930. {
  931. switch (pEntry->GetEntryType())
  932. {
  933. case BUFFER_ENTRY_TYPE_VALID:
  934. hr = InsertDCListView(pEntry);
  935. if (SUCCEEDED(hr))
  936. break;
  937. // fall through if error
  938. case BUFFER_ENTRY_TYPE_ERROR:
  939. RefreshDCListViewErrorReport(csDomain, hr);
  940. break;
  941. default:
  942. ASSERT(FALSE);
  943. break;
  944. }
  945. }
  946. }
  947. void CChooseDCDlg::RefreshDCListViewErrorReport(
  948. IN PCTSTR pszDomainName,
  949. IN HRESULT hr
  950. )
  951. {
  952. PVOID apv[1];
  953. apv[0] = static_cast<PVOID>(const_cast<PTSTR>(pszDomainName));
  954. ReportErrorEx(m_hWnd, IDS_NO_DCS_FOUND, hr,
  955. MB_OK | MB_ICONINFORMATION, apv, 1, 0);
  956. InsertSpecialMsg(FALSE); // insert "Error"
  957. if (m_bSiteRepl)
  958. (GetDlgItem(IDC_SELECTDC_DOMAIN))->SetFocus();
  959. else
  960. (GetDlgItem(IDC_SELECTDC_DCEDIT))->SetFocus();
  961. }
  962. void CChooseDCDlg::RefreshDCListView()
  963. {
  964. CString csDomain, csFormat, csText;
  965. GetDlgItemText(IDC_SELECTDC_DOMAIN, csDomain);
  966. if ( csDomain.IsEmpty() ||
  967. (0 == csDomain.CompareNoCase(m_csPrevDomain)) )
  968. return;
  969. TRACE(_T("CChooseDCDlg::RefreshDCListView for %s\n"), csDomain);
  970. //
  971. // update m_csPrevDomain
  972. // to prevent LoadInfo() from being invoked multiple times when
  973. // a serial of WM_KILLFOCUS happening on the same DomainName
  974. //
  975. m_csPrevDomain = csDomain;
  976. //
  977. // clear dc edit box
  978. //
  979. SetDlgItemText(IDC_SELECTDC_DCEDIT, _T(""));
  980. //
  981. // update the msg on top of the dc list view
  982. //
  983. csFormat.LoadString(IDS_SELECTDC_DCLISTVIEW_TITLE);
  984. csText.Format(csFormat, csDomain);
  985. SetDlgItemText(IDC_SELECTDC_DCLISTVIEW_TITLE, csText);
  986. if (m_pDCBufferManager)
  987. {
  988. //
  989. // insert "Waiting..." into the list view control
  990. //
  991. InsertSpecialMsg(TRUE);
  992. UpdateWindow();
  993. CWaitCursor cwait;
  994. //
  995. // Make sure csDomain is a valid domain name
  996. //
  997. CString csSelectedDomainDns;
  998. HRESULT hr = GetDnsNameOfDomainOrForest(
  999. csDomain,
  1000. csSelectedDomainDns,
  1001. TRUE,
  1002. TRUE); // We're interested in domain name not forest name here
  1003. if (FAILED(hr))
  1004. {
  1005. RefreshDCListViewErrorReport(csDomain, hr);
  1006. return;
  1007. }
  1008. if (csSelectedDomainDns.IsEmpty())
  1009. {
  1010. // down-level domain
  1011. PVOID apv[1];
  1012. apv[0] = static_cast<PVOID>(const_cast<LPTSTR>(static_cast<LPCTSTR>(csDomain)));
  1013. ReportMessageEx(m_hWnd, IDS_SELECTDC_DOWNLEVEL_DOMAIN,
  1014. MB_OK | MB_ICONSTOP, apv, 1);
  1015. InsertSpecialMsg(FALSE); // insert "Error"
  1016. (GetDlgItem(IDC_SELECTDC_DOMAIN))->SetFocus();
  1017. return;
  1018. }
  1019. //
  1020. // start the thread to calculate a list of DCs in the current selected domain
  1021. //
  1022. CDCSITEINFO *pEntry = NULL;
  1023. hr = m_pDCBufferManager->LoadInfo(csSelectedDomainDns, &pEntry);
  1024. if (SUCCEEDED(hr))
  1025. {
  1026. //
  1027. // Either we get a valid ptr back (ie. data is ready), insert it;
  1028. // or, a thread is alreay in progress, wait until a THREAD_DONE message.
  1029. //
  1030. if (pEntry)
  1031. {
  1032. ASSERT(pEntry->GetEntryType() == BUFFER_ENTRY_TYPE_VALID);
  1033. hr = InsertDCListView(pEntry);
  1034. }
  1035. }
  1036. if (FAILED(hr))
  1037. RefreshDCListViewErrorReport(csSelectedDomainDns, hr);
  1038. }
  1039. return;
  1040. }
  1041. //+---------------------------------------------------------------------------
  1042. //
  1043. // Function: CChooseDCDlg::FreeDCItems
  1044. //
  1045. // Synopsis: Clear the lParam associated with each item in the list view control.
  1046. // The lParam is needed to support column-sorting.
  1047. //
  1048. //----------------------------------------------------------------------------
  1049. void
  1050. CChooseDCDlg::FreeDCItems(CListCtrl& clv)
  1051. {
  1052. int index = -1;
  1053. LPARAM lParam = 0;
  1054. while ( -1 != (index = clv.GetNextItem(index, LVNI_ALL)) )
  1055. {
  1056. lParam = clv.GetItemData(index);
  1057. if (lParam)
  1058. delete ((DCLISTVIEWITEM *)lParam);
  1059. }
  1060. ListView_DeleteAllItems(clv.GetSafeHwnd());
  1061. }
  1062. void CChooseDCDlg::DoContextHelp(HWND hWndControl)
  1063. {
  1064. if (hWndControl)
  1065. {
  1066. ::WinHelp(hWndControl,
  1067. DSADMIN_CONTEXT_HELP_FILE,
  1068. HELP_WM_HELP,
  1069. (DWORD_PTR)(LPTSTR)g_aHelpIDs_IDD_SELECT_DC);
  1070. }
  1071. }
  1072. /////////////////////////////////////////////////////////////////////////
  1073. // CDsAdminChooseDCObj
  1074. STDMETHODIMP CDsAdminChooseDCObj::InvokeDialog(
  1075. /*IN*/ HWND hwndParent,
  1076. /*IN*/ LPCWSTR lpszTargetDomain,
  1077. /*IN*/ LPCWSTR lpszTargetDomainController,
  1078. /*IN*/ ULONG uFlags,
  1079. /*OUT*/ BSTR* bstrSelectedDC)
  1080. {
  1081. TRACE(L"CDsAdminChooseDCObj::InvokeDialog(\n");
  1082. TRACE(L" HWND hwndParent = 0x%x\n", hwndParent);
  1083. TRACE(L" LPCWSTR lpszTargetDomain = %s\n", lpszTargetDomain);
  1084. TRACE(L" LPCWSTR lpszTargetDomainController = %s\n", lpszTargetDomainController);
  1085. TRACE(L" ULONG uFlags = 0x%x\n", uFlags);
  1086. TRACE(L" BSTR* bstrSelectedDC = 0x%x)\n", bstrSelectedDC);
  1087. if (!::IsWindow(hwndParent) || (bstrSelectedDC == NULL))
  1088. {
  1089. TRACE(L"InvokeDialog() Failed, invalid arg.\n");
  1090. return E_INVALIDARG;
  1091. }
  1092. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1093. CChooseDCDlg DCdlg(CWnd::FromHandle(hwndParent));
  1094. // load current bind info
  1095. DCdlg.m_bSiteRepl = TRUE;
  1096. DCdlg.m_csTargetDomain = lpszTargetDomain;
  1097. DCdlg.m_csTargetDomainController = lpszTargetDomainController;
  1098. //
  1099. // invoke the dialog
  1100. //
  1101. HRESULT hr = S_FALSE;
  1102. if (DCdlg.DoModal() == IDOK)
  1103. {
  1104. TRACE(L"DCdlg.DoModal() returned IDOK\n");
  1105. TRACE(L"DCdlg.m_csTargetDomainController = <%s>\n", (LPCWSTR)(DCdlg.m_csTargetDomainController));
  1106. TRACE(L"DCdlg.m_csTargetDomain = <%s>\n", (LPCWSTR)(DCdlg.m_csTargetDomain));
  1107. LPCWSTR lpsz = NULL;
  1108. if (DCdlg.m_csTargetDomainController.IsEmpty())
  1109. {
  1110. lpsz = DCdlg.m_csTargetDomain;
  1111. }
  1112. else
  1113. {
  1114. lpsz = DCdlg.m_csTargetDomainController;
  1115. }
  1116. *bstrSelectedDC = ::SysAllocString(lpsz);
  1117. TRACE(L"returning *bstrSelectedDC = <%s>\n", *bstrSelectedDC);
  1118. hr = S_OK;
  1119. }
  1120. TRACE(L"InvokeDialog() returning hr = 0x%x\n", hr);
  1121. return hr;
  1122. }
  1123. /////////////////////////////////////////////////////////////////////////////
  1124. // CRenameUserDlg dialog
  1125. CRenameUserDlg::CRenameUserDlg(CDSComponentData* pComponentData, CWnd* pParent /*=NULL*/)
  1126. : m_pComponentData(pComponentData),
  1127. CHelpDialog(CRenameUserDlg::IDD, pParent)
  1128. {
  1129. //{{AFX_DATA_INIT(CRenameUserDlg)
  1130. m_login = _T("");
  1131. m_samaccountname = _T("");
  1132. m_domain = _T("");
  1133. m_dldomain = _T("");
  1134. m_first = _T("");
  1135. m_last = _T("");
  1136. m_cn = _T("");
  1137. m_oldcn = _T("");
  1138. m_displayname = _T("");
  1139. //}}AFX_DATA_INIT
  1140. }
  1141. void CRenameUserDlg::DoDataExchange(CDataExchange* pDX)
  1142. {
  1143. CHelpDialog::DoDataExchange(pDX);
  1144. //{{AFX_DATA_MAP(CRenameUserDlg)
  1145. DDX_Text(pDX, IDC_EDIT_OBJECT_NAME, m_cn);
  1146. DDX_Text(pDX, IDC_EDIT_DISPLAY_NAME, m_displayname);
  1147. DDX_Text(pDX, IDC_FIRST_NAME_EDIT, m_first);
  1148. DDX_Text(pDX, IDC_LAST_NAME_EDIT, m_last);
  1149. DDX_Text(pDX, IDC_NT5_USER_EDIT, m_login);
  1150. DDX_Text(pDX, IDC_NT4_USER_EDIT, m_samaccountname);
  1151. DDX_Text(pDX, IDC_NT4_DOMAIN_EDIT, m_dldomain);
  1152. DDX_CBString(pDX, IDC_NT5_DOMAIN_COMBO, m_domain);
  1153. //}}AFX_DATA_MAP
  1154. }
  1155. BEGIN_MESSAGE_MAP(CRenameUserDlg, CHelpDialog)
  1156. //{{AFX_MSG_MAP(CRenameUserDlg)
  1157. ON_EN_CHANGE(IDC_EDIT_OBJECT_NAME, OnObjectNameChange)
  1158. ON_EN_CHANGE(IDC_FIRST_NAME_EDIT, OnNameChange)
  1159. ON_EN_CHANGE(IDC_LAST_NAME_EDIT, OnNameChange)
  1160. ON_EN_CHANGE(IDC_NT5_USER_EDIT, OnUserNameChange)
  1161. //}}AFX_MSG_MAP
  1162. END_MESSAGE_MAP()
  1163. /////////////////////////////////////////////////////////////////////////////
  1164. // CRenameUserDlg message handlers
  1165. BOOL CRenameUserDlg::OnInitDialog()
  1166. {
  1167. CHelpDialog::OnInitDialog();
  1168. CString csdomain;
  1169. m_nameFormatter.Initialize(m_pComponentData->GetBasePathsInfo(),
  1170. L"user");
  1171. ((CComboBox*)GetDlgItem (IDC_NT5_DOMAIN_COMBO))->AddString (m_domain);
  1172. ((CComboBox*)GetDlgItem (IDC_NT5_DOMAIN_COMBO))->SetCurSel(0);
  1173. POSITION pos = m_domains.GetHeadPosition();
  1174. while (pos != NULL) {
  1175. csdomain = m_domains.GetNext(INOUT pos);
  1176. ((CComboBox*)GetDlgItem (IDC_NT5_DOMAIN_COMBO))->AddString (csdomain);
  1177. }
  1178. ((CEdit *)GetDlgItem(IDC_EDIT_OBJECT_NAME))->SetLimitText(64);
  1179. ((CEdit *)GetDlgItem(IDC_FIRST_NAME_EDIT))->SetLimitText(64);
  1180. ((CEdit *)GetDlgItem(IDC_LAST_NAME_EDIT))->SetLimitText(64);
  1181. ((CEdit *)GetDlgItem(IDC_EDIT_DISPLAY_NAME))->SetLimitText(259);
  1182. ((CEdit *)GetDlgItem(IDC_NT4_USER_EDIT))->SetLimitText(20);
  1183. CString szObjectName;
  1184. GetDlgItemText(IDC_EDIT_OBJECT_NAME, szObjectName);
  1185. szObjectName.TrimLeft();
  1186. szObjectName.TrimRight();
  1187. if (szObjectName.IsEmpty())
  1188. {
  1189. GetDlgItem(IDOK)->EnableWindow(FALSE);
  1190. }
  1191. return TRUE; // return TRUE unless you set the focus to a control
  1192. // EXCEPTION: OCX Property Pages should return FALSE
  1193. }
  1194. void CRenameUserDlg::OnObjectNameChange()
  1195. {
  1196. CString szObjectName;
  1197. GetDlgItemText(IDC_EDIT_OBJECT_NAME, szObjectName);
  1198. szObjectName.TrimLeft();
  1199. szObjectName.TrimRight();
  1200. if (szObjectName.IsEmpty())
  1201. {
  1202. GetDlgItem(IDOK)->EnableWindow(FALSE);
  1203. }
  1204. else
  1205. {
  1206. GetDlgItem(IDOK)->EnableWindow(TRUE);
  1207. }
  1208. }
  1209. void CRenameUserDlg::OnNameChange()
  1210. {
  1211. GetDlgItemText(IDC_EDIT_FIRST_NAME, OUT m_first);
  1212. GetDlgItemText(IDC_EDIT_LAST_NAME, OUT m_last);
  1213. m_first.TrimLeft();
  1214. m_first.TrimRight();
  1215. m_last.TrimLeft();
  1216. m_last.TrimRight();
  1217. m_nameFormatter.FormatName(m_cn,
  1218. m_first.IsEmpty() ? NULL : (LPCWSTR)m_first,
  1219. NULL,
  1220. m_last.IsEmpty() ? NULL : (LPCWSTR)m_last);
  1221. SetDlgItemText(IDC_EDIT_DISPLAY_NAME, m_cn);
  1222. }
  1223. void CRenameUserDlg::OnUserNameChange()
  1224. {
  1225. GetDlgItemText(IDC_NT5_USER_EDIT, m_login);
  1226. SetDlgItemText(IDC_NT4_USER_EDIT, m_login);
  1227. }
  1228. void CRenameUserDlg::DoContextHelp(HWND hWndControl)
  1229. {
  1230. if (hWndControl)
  1231. {
  1232. ::WinHelp(hWndControl,
  1233. DSADMIN_CONTEXT_HELP_FILE,
  1234. HELP_WM_HELP,
  1235. (DWORD_PTR)(LPTSTR)g_aHelpIDs_IDD_RENAME_USER);
  1236. }
  1237. }
  1238. /////////////////////////////////////////////////////////////////////////////
  1239. // CRenameGroupDlg message handlers
  1240. BOOL CRenameGroupDlg::OnInitDialog()
  1241. {
  1242. CHelpDialog::OnInitDialog();
  1243. ((CEdit *)GetDlgItem(IDC_EDIT_OBJECT_NAME))->SetLimitText(64);
  1244. ((CEdit *)GetDlgItem(IDC_NT4_USER_EDIT))->SetLimitText(m_samtextlimit);
  1245. return TRUE; // return TRUE unless you set the focus to a control
  1246. // EXCEPTION: OCX Property Pages should return FALSE
  1247. }
  1248. /////////////////////////////////////////////////////////////////////////////
  1249. // CRenameGroupDlg dialog
  1250. CRenameGroupDlg::CRenameGroupDlg(CWnd* pParent /*=NULL*/)
  1251. : CHelpDialog(CRenameGroupDlg::IDD, pParent)
  1252. {
  1253. //{{AFX_DATA_INIT(CRenameGroupDlg)
  1254. m_samaccountname = _T("");
  1255. m_cn = _T("");
  1256. m_samtextlimit = 256;
  1257. //}}AFX_DATA_INIT
  1258. }
  1259. void CRenameGroupDlg::DoDataExchange(CDataExchange* pDX)
  1260. {
  1261. CHelpDialog::DoDataExchange(pDX);
  1262. //{{AFX_DATA_MAP(CRenameGroupDlg)
  1263. DDX_Text(pDX, IDC_NT4_USER_EDIT, m_samaccountname);
  1264. DDX_Text(pDX, IDC_EDIT_OBJECT_NAME, m_cn);
  1265. //}}AFX_DATA_MAP
  1266. }
  1267. BEGIN_MESSAGE_MAP(CRenameGroupDlg, CHelpDialog)
  1268. //{{AFX_MSG_MAP(CRenameGroupDlg)
  1269. //}}AFX_MSG_MAP
  1270. END_MESSAGE_MAP()
  1271. void CRenameGroupDlg::DoContextHelp(HWND hWndControl)
  1272. {
  1273. if (hWndControl)
  1274. {
  1275. ::WinHelp(hWndControl,
  1276. DSADMIN_CONTEXT_HELP_FILE,
  1277. HELP_WM_HELP,
  1278. (DWORD_PTR)(LPTSTR)g_aHelpIDs_IDD_RENAME_GROUP);
  1279. }
  1280. }
  1281. /////////////////////////////////////////////////////////////////////////////
  1282. // CRenameContactDlg message handlers
  1283. BOOL CRenameContactDlg::OnInitDialog()
  1284. {
  1285. CHelpDialog::OnInitDialog();
  1286. return TRUE; // return TRUE unless you set the focus to a control
  1287. // EXCEPTION: OCX Property Pages should return FALSE
  1288. }
  1289. void CRenameContactDlg::DoContextHelp(HWND hWndControl)
  1290. {
  1291. if (hWndControl)
  1292. {
  1293. ::WinHelp(hWndControl,
  1294. DSADMIN_CONTEXT_HELP_FILE,
  1295. HELP_WM_HELP,
  1296. (DWORD_PTR)(LPTSTR)g_aHelpIDs_IDD_RENAME_CONTACT);
  1297. }
  1298. }
  1299. /////////////////////////////////////////////////////////////////////////////
  1300. // CRenameContactDlg dialog
  1301. CRenameContactDlg::CRenameContactDlg(CWnd* pParent /*=NULL*/)
  1302. : CHelpDialog(CRenameContactDlg::IDD, pParent)
  1303. {
  1304. //{{AFX_DATA_INIT(CRenameContactDlg)
  1305. m_cn = _T("");
  1306. m_first = _T("");
  1307. m_last = _T("");
  1308. m_disp = _T("");
  1309. //}}AFX_DATA_INIT
  1310. }
  1311. void CRenameContactDlg::DoDataExchange(CDataExchange* pDX)
  1312. {
  1313. CHelpDialog::DoDataExchange(pDX);
  1314. //{{AFX_DATA_MAP(CRenameContactDlg)
  1315. DDX_Text(pDX, IDC_EDIT_OBJECT_NAME, m_cn);
  1316. DDX_Text(pDX, IDC_FIRST_NAME_EDIT, m_first);
  1317. DDX_Text(pDX, IDC_LAST_NAME_EDIT, m_last);
  1318. DDX_Text(pDX, IDC_DISP_NAME_EDIT, m_disp);
  1319. //}}AFX_DATA_MAP
  1320. }
  1321. BEGIN_MESSAGE_MAP(CRenameContactDlg, CHelpDialog)
  1322. //{{AFX_MSG_MAP(CRenameContactDlg)
  1323. //}}AFX_MSG_MAP
  1324. END_MESSAGE_MAP()
  1325. /////////////////////////////////////////////////////////////////////////////
  1326. // CRenameGenericDlg message handlers
  1327. BOOL CRenameGenericDlg::OnInitDialog()
  1328. {
  1329. CHelpDialog::OnInitDialog();
  1330. ((CEdit *)GetDlgItem(IDC_EDIT_OBJECT_NAME))->SetLimitText(64);
  1331. return TRUE; // return TRUE unless you set the focus to a control
  1332. // EXCEPTION: OCX Property Pages should return FALSE
  1333. }
  1334. /////////////////////////////////////////////////////////////////////////////
  1335. // CRenameGenericDlg dialog
  1336. CRenameGenericDlg::CRenameGenericDlg(CWnd* pParent /*=NULL*/)
  1337. : CHelpDialog(CRenameGenericDlg::IDD, pParent)
  1338. {
  1339. //{{AFX_DATA_INIT(CRenameGenericDlg)
  1340. m_cn = _T("");
  1341. //}}AFX_DATA_INIT
  1342. }
  1343. void CRenameGenericDlg::DoDataExchange(CDataExchange* pDX)
  1344. {
  1345. CHelpDialog::DoDataExchange(pDX);
  1346. //{{AFX_DATA_MAP(CRenameGenericDlg)
  1347. DDX_Text(pDX, IDC_EDIT_OBJECT_NAME, m_cn);
  1348. //}}AFX_DATA_MAP
  1349. }
  1350. BEGIN_MESSAGE_MAP(CRenameGenericDlg, CHelpDialog)
  1351. //{{AFX_MSG_MAP(CRenameGenericDlg)
  1352. //}}AFX_MSG_MAP
  1353. END_MESSAGE_MAP()
  1354. void CRenameGenericDlg::DoContextHelp(HWND hWndControl)
  1355. {
  1356. if (hWndControl)
  1357. {
  1358. ::WinHelp(hWndControl,
  1359. DSADMIN_CONTEXT_HELP_FILE,
  1360. HELP_WM_HELP,
  1361. (DWORD_PTR)(LPTSTR)g_aHelpIDs_IDD_RENAME_COMPUTER);
  1362. }
  1363. }
  1364. /////////////////////////////////////////////////////////////////////////////
  1365. // CSpecialMessageBox dialog
  1366. CSpecialMessageBox::CSpecialMessageBox(CWnd* pParent /*=NULL*/)
  1367. : CDialog(CSpecialMessageBox::IDD, pParent)
  1368. {
  1369. //{{AFX_DATA_INIT(CSpecialMessageBox)
  1370. m_title = _T("");
  1371. m_message = _T("");
  1372. //}}AFX_DATA_INIT
  1373. }
  1374. void CSpecialMessageBox::DoDataExchange(CDataExchange* pDX)
  1375. {
  1376. CDialog::DoDataExchange(pDX);
  1377. //{{AFX_DATA_MAP(CSpecialMessageBox)
  1378. DDX_Text(pDX, IDC_STATIC_MESSAGE, m_message);
  1379. //}}AFX_DATA_MAP
  1380. }
  1381. BEGIN_MESSAGE_MAP(CSpecialMessageBox, CDialog)
  1382. //{{AFX_MSG_MAP(CSpecialMessageBox)
  1383. ON_BN_CLICKED(IDC_BUTTON_YES, OnYesButton)
  1384. ON_BN_CLICKED(IDC_BUTTON_NO, OnNoButton)
  1385. ON_BN_CLICKED(IDC_BUTTON_YESTOALL, OnYesToAllButton)
  1386. //}}AFX_MSG_MAP
  1387. END_MESSAGE_MAP()
  1388. /////////////////////////////////////////////////////////////////////////////
  1389. // CSpecialMessageBox message handlers
  1390. BOOL CSpecialMessageBox::OnInitDialog()
  1391. {
  1392. CDialog::OnInitDialog();
  1393. if (!m_title.IsEmpty()) {
  1394. SetWindowText (m_title);
  1395. }
  1396. GetDlgItem(IDC_BUTTON_NO)->SetFocus();
  1397. return FALSE; // return TRUE unless you set the focus to a control
  1398. // EXCEPTION: OCX Property Pages should return FALSE
  1399. }
  1400. void
  1401. CSpecialMessageBox::OnYesButton()
  1402. {
  1403. CDialog::EndDialog (IDYES);
  1404. }
  1405. void
  1406. CSpecialMessageBox::OnNoButton()
  1407. {
  1408. CDialog::EndDialog (IDNO);
  1409. }
  1410. void
  1411. CSpecialMessageBox::OnYesToAllButton()
  1412. {
  1413. CDialog::EndDialog (IDC_BUTTON_YESTOALL);
  1414. }
  1415. #ifdef FIXUPDC
  1416. /////////////////////////////////////////////////////////////////////////////
  1417. // CFixupDC dialog
  1418. CFixupDC::CFixupDC(CWnd* pParent /*=NULL*/)
  1419. : CHelpDialog(CFixupDC::IDD, pParent)
  1420. {
  1421. //{{AFX_DATA_INIT(CFixupDC)
  1422. m_strServer = _T("");
  1423. //}}AFX_DATA_INIT
  1424. for (int i=0; i<NUM_FIXUP_OPTIONS; i++) {
  1425. m_bCheck[i] = FALSE;
  1426. }
  1427. }
  1428. void CFixupDC::DoDataExchange(CDataExchange* pDX)
  1429. {
  1430. CHelpDialog::DoDataExchange(pDX);
  1431. //{{AFX_DATA_MAP(CFixupDC)
  1432. DDX_Text(pDX, IDC_FIXUP_DC_SERVER, m_strServer);
  1433. //}}AFX_DATA_MAP
  1434. DDX_Check(pDX, IDC_FIXUP_DC_CHECK0, m_bCheck[0]);
  1435. DDX_Check(pDX, IDC_FIXUP_DC_CHECK1, m_bCheck[1]);
  1436. DDX_Check(pDX, IDC_FIXUP_DC_CHECK2, m_bCheck[2]);
  1437. DDX_Check(pDX, IDC_FIXUP_DC_CHECK3, m_bCheck[3]);
  1438. DDX_Check(pDX, IDC_FIXUP_DC_CHECK4, m_bCheck[4]);
  1439. DDX_Check(pDX, IDC_FIXUP_DC_CHECK5, m_bCheck[5]);
  1440. }
  1441. BEGIN_MESSAGE_MAP(CFixupDC, CHelpDialog)
  1442. //{{AFX_MSG_MAP(CFixupDC)
  1443. //}}AFX_MSG_MAP
  1444. END_MESSAGE_MAP()
  1445. /////////////////////////////////////////////////////////////////////////////
  1446. // CFixupDC message handlers
  1447. extern FixupOptionsMsg g_FixupOptionsMsg[];
  1448. BOOL CFixupDC::OnInitDialog()
  1449. {
  1450. CHelpDialog::OnInitDialog();
  1451. HWND hCheck = NULL;
  1452. GetDlgItem(IDC_FIXUP_DC_CHECK0, &hCheck);
  1453. ::SetFocus(hCheck);
  1454. for (int i=0; i<NUM_FIXUP_OPTIONS; i++)
  1455. m_bCheck[i] = g_FixupOptionsMsg[i].bDefaultOn;
  1456. UpdateData(FALSE);
  1457. return FALSE; // return TRUE unless you set the focus to a control
  1458. // EXCEPTION: OCX Property Pages should return FALSE
  1459. }
  1460. void CFixupDC::OnOK()
  1461. {
  1462. UpdateData(TRUE);
  1463. // make sure user has selected some checkboxes
  1464. BOOL bCheck = FALSE;
  1465. for (int i=0; !bCheck && (i<NUM_FIXUP_OPTIONS); i++) {
  1466. bCheck = bCheck || m_bCheck[i];
  1467. }
  1468. if (!bCheck)
  1469. {
  1470. ReportMessageEx(m_hWnd, IDS_FIXUP_DC_SELECTION_WARNING, MB_OK);
  1471. return;
  1472. }
  1473. CHelpDialog::OnOK();
  1474. }
  1475. void CFixupDC::DoContextHelp(HWND hWndControl)
  1476. {
  1477. if (hWndControl)
  1478. {
  1479. ::WinHelp(hWndControl,
  1480. DSADMIN_CONTEXT_HELP_FILE,
  1481. HELP_WM_HELP,
  1482. (DWORD_PTR)(LPTSTR)g_aHelpIDs_IDD_FIXUP_DC);
  1483. }
  1484. }
  1485. #endif // FIXUPDC
  1486. /////////////////////////////////////////////////////////////////////////////
  1487. // CPasswordDlg dialog
  1488. CPasswordDlg::CPasswordDlg(CWnd* pParent /*=NULL*/)
  1489. : CHelpDialog(CPasswordDlg::IDD, pParent)
  1490. {
  1491. //{{AFX_DATA_INIT(CPasswordDlg)
  1492. m_strPassword = _T("");
  1493. m_strUserName = _T("");
  1494. //}}AFX_DATA_INIT
  1495. }
  1496. void CPasswordDlg::DoDataExchange(CDataExchange* pDX)
  1497. {
  1498. CHelpDialog::DoDataExchange(pDX);
  1499. //{{AFX_DATA_MAP(CPasswordDlg)
  1500. DDX_Text(pDX, IDC_PASSWORD, m_strPassword);
  1501. DDX_Text(pDX, IDC_USER_NAME, m_strUserName);
  1502. //}}AFX_DATA_MAP
  1503. }
  1504. BEGIN_MESSAGE_MAP(CPasswordDlg, CHelpDialog)
  1505. //{{AFX_MSG_MAP(CPasswordDlg)
  1506. //}}AFX_MSG_MAP
  1507. END_MESSAGE_MAP()
  1508. /////////////////////////////////////////////////////////////////////////////
  1509. // CPasswordDlg message handlers
  1510. void CPasswordDlg::OnOK()
  1511. {
  1512. UpdateData(TRUE);
  1513. if (m_strUserName.IsEmpty()) {
  1514. ReportMessageEx(m_hWnd, IDS_PASSWORD_DLG_WARNING, MB_OK);
  1515. return;
  1516. }
  1517. CHelpDialog::OnOK();
  1518. }
  1519. void CPasswordDlg::DoContextHelp(HWND hWndControl)
  1520. {
  1521. if (hWndControl)
  1522. {
  1523. ::WinHelp(hWndControl,
  1524. DSADMIN_CONTEXT_HELP_FILE,
  1525. HELP_WM_HELP,
  1526. (DWORD_PTR)(LPTSTR)g_aHelpIDs_IDD_PASSWORD);
  1527. }
  1528. }