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.

505 lines
13 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: fsmoui.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // File: fsmoui.cpp
  11. #include "stdafx.h"
  12. #include "dsutil.h"
  13. #include "util.h"
  14. #include "uiutil.h"
  15. #include "fsmoui.h"
  16. #include "helpids.h"
  17. #include "dsgetdc.h" //DsEnumerateDomainTrusts
  18. #include "lm.h" //NetApiBufferFree
  19. #ifdef _DEBUG
  20. #define new DEBUG_NEW
  21. #undef THIS_FILE
  22. static char THIS_FILE[] = __FILE__;
  23. #endif
  24. //////////////////////////////////////////////////////////////////
  25. // CFsmoPropertyPage
  26. BEGIN_MESSAGE_MAP(CFsmoPropertyPage, CPropertyPage)
  27. ON_BN_CLICKED(IDC_CHANGE_FSMO, OnChange)
  28. ON_WM_HELPINFO()
  29. END_MESSAGE_MAP()
  30. CFsmoPropertyPage::CFsmoPropertyPage(CFsmoPropertySheet* pSheet, FSMO_TYPE fsmoType)
  31. {
  32. m_pSheet = pSheet;
  33. m_fsmoType = fsmoType;
  34. // load the caption (tab control text) depending on the FSMO type
  35. UINT nIDCaption = 0;
  36. switch (m_fsmoType)
  37. {
  38. case RID_POOL_FSMO:
  39. nIDCaption = IDS_RID_POOL_FSMO;
  40. break;
  41. case PDC_FSMO:
  42. nIDCaption = IDS_PDC_FSMO;
  43. break;
  44. case INFRASTUCTURE_FSMO:
  45. nIDCaption = IDS_INFRASTRUCTURE_FSMO;
  46. break;
  47. };
  48. Construct(IDD_FSMO_PAGE, nIDCaption);
  49. }
  50. BOOL CFsmoPropertyPage::OnInitDialog()
  51. {
  52. CPropertyPage::OnInitDialog();
  53. //
  54. // We just want a close button since we are not applying any changes
  55. // directly from this page
  56. //
  57. ::SendMessage(GetParent()->GetSafeHwnd(), PSM_CANCELTOCLOSE, 0, 0);
  58. // init the status (online/offline) control)
  59. m_fsmoServerState.Init(::GetDlgItem(m_hWnd, IDC_STATIC_FSMO_STATUS));
  60. // set the server we are focused on
  61. SetDlgItemText(IDC_EDIT_CURRENT_DC, m_pSheet->GetBasePathsInfo()->GetServerName());
  62. // set the FSMO description
  63. CString szDesc;
  64. switch (m_fsmoType)
  65. {
  66. case RID_POOL_FSMO:
  67. VERIFY(szDesc.LoadString(IDS_RID_POOL_FSMO_DESC));
  68. break;
  69. case PDC_FSMO:
  70. VERIFY(szDesc.LoadString(IDS_PDC_FSMO_DESC));
  71. break;
  72. case INFRASTUCTURE_FSMO:
  73. VERIFY(szDesc.LoadString(IDS_INFRASTRUCTURE_FSMO_DESC));
  74. break;
  75. };
  76. SetDlgItemText(IDC_STATIC_FSMO_DESC, szDesc);
  77. { // scope for the wait cursor object
  78. CWaitCursor wait;
  79. // retrieve the FSMO owner
  80. MyBasePathsInfo fsmoOwnerInfo;
  81. PWSTR pszFsmoOwner = 0;
  82. HRESULT hr = FindFsmoOwner(m_pSheet->GetBasePathsInfo(), m_fsmoType, &fsmoOwnerInfo,
  83. &pszFsmoOwner);
  84. if (SUCCEEDED(hr) && pszFsmoOwner)
  85. {
  86. m_szFsmoOwnerServerName = pszFsmoOwner;
  87. delete[] pszFsmoOwner;
  88. pszFsmoOwner = 0;
  89. }
  90. _SetFsmoServerStatus(SUCCEEDED(hr));
  91. }
  92. return TRUE;
  93. }
  94. #ifdef DBG
  95. UINT GetInfoFromIniFileIfDBG(LPCWSTR lpszSection, LPCWSTR lpszKey, INT nDefault = 0)
  96. {
  97. static LPCWSTR lpszFile = L"\\system32\\dsadmin.ini";
  98. WCHAR szFilePath[2*MAX_PATH];
  99. UINT nLen = ::GetSystemWindowsDirectory(szFilePath, 2*MAX_PATH);
  100. if (nLen == 0)
  101. return nDefault;
  102. wcscat(szFilePath, lpszFile);
  103. return ::GetPrivateProfileInt(lpszSection, lpszKey, nDefault, szFilePath);
  104. }
  105. #endif
  106. void CFsmoPropertyPage::OnChange()
  107. {
  108. // Test stuff
  109. /*
  110. {
  111. HRESULT hrTest = E_OUTOFMEMORY;
  112. BOOL bTest = AllowForcedTransfer(hrTest);
  113. return;
  114. }
  115. */
  116. // verify we have different servers
  117. if (m_szFsmoOwnerServerName.CompareNoCase(m_pSheet->GetBasePathsInfo()->GetServerName()) == 0)
  118. {
  119. ReportErrorEx(m_hWnd,IDS_WARNING_FSMO_CHANGE_FOCUS,S_OK,
  120. MB_OK | MB_ICONERROR, NULL, 0);
  121. return;
  122. }
  123. bool bConfirm = false; //ask for confirmation only once
  124. if( m_fsmoType == INFRASTUCTURE_FSMO )
  125. {
  126. //check if target DC is GC
  127. //Try to bind to GC port, fails if not GC
  128. IADs *pObject;
  129. HRESULT hr1;
  130. CString strServer = L"GC://";
  131. strServer += m_pSheet->GetBasePathsInfo()->GetServerName();
  132. hr1 = DSAdminOpenObject(strServer,
  133. IID_IADs,
  134. (void**) &pObject,
  135. TRUE /*bServer*/);
  136. if (SUCCEEDED(hr1))
  137. {
  138. //Release Interface, we don't need it
  139. pObject->Release();
  140. //Check if domain has any trusted domains
  141. DS_DOMAIN_TRUSTS *Domains;
  142. DWORD result;
  143. ULONG DomainCount=0;
  144. result = DsEnumerateDomainTrusts (
  145. (LPWSTR)m_pSheet->GetBasePathsInfo()->GetServerName(),
  146. DS_DOMAIN_DIRECT_OUTBOUND|
  147. DS_DOMAIN_DIRECT_INBOUND,
  148. &Domains,
  149. &DomainCount
  150. );
  151. if( HRESULT_CODE(result) == NO_ERROR )
  152. {
  153. if( DomainCount > 0 )
  154. {
  155. //If all the trusted domains are downlevel, it doesn't matter
  156. bool bAllDownLevel = true;
  157. for( ULONG i = 0; i < DomainCount; ++i )
  158. {
  159. if( Domains[i].DnsDomainName != NULL )
  160. {
  161. bAllDownLevel = false;
  162. break;
  163. }
  164. }
  165. NetApiBufferFree( Domains );
  166. if( false == bAllDownLevel )
  167. {
  168. LPTSTR ptzFormat = NULL;
  169. LPTSTR ptzMessage = NULL;
  170. int cch = 0;
  171. INT_PTR retval;
  172. // load message format
  173. if (!LoadStringToTchar(IDS_IFSMO_TARGET_DC_IS_GC, &ptzFormat))
  174. {
  175. ASSERT(FALSE);
  176. }
  177. PVOID apv[2] = {
  178. NULL,
  179. (LPWSTR)m_pSheet->GetBasePathsInfo()->GetServerName()
  180. };
  181. // generate actual message
  182. cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
  183. | FORMAT_MESSAGE_FROM_STRING
  184. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  185. ptzFormat,
  186. NULL,
  187. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  188. (PTSTR)&ptzMessage, 0, (va_list*)apv);
  189. if (!cch)
  190. {
  191. ASSERT(FALSE);
  192. }
  193. CMoreInfoMessageBox dlg(m_hWnd,
  194. m_pSheet->GetIDisplayHelp(),
  195. TRUE );
  196. dlg.SetMessage(ptzMessage);
  197. dlg.SetURL(DSADMIN_MOREINFO_FSMO_TARGET_DC_IS_GC);
  198. retval = dlg.DoModal();
  199. bConfirm = true;
  200. //clean up
  201. if( NULL != ptzFormat )
  202. delete ptzFormat;
  203. if( NULL != ptzMessage )
  204. LocalFree(ptzMessage);
  205. if( retval == IDCANCEL )
  206. return;
  207. }
  208. }
  209. }
  210. }
  211. }
  212. // make sure the user wants to do it
  213. if (!bConfirm && ReportErrorEx(m_hWnd,IDS_CHANGE_FSMO_CONFIRMATION,S_OK,
  214. MB_YESNO | MB_ICONWARNING, NULL, 0) != IDYES)
  215. return;
  216. // try a graceful transfer
  217. HRESULT hr;
  218. { // scope for the wait cursor object
  219. CWaitCursor wait;
  220. if ( m_fsmoType == PDC_FSMO )
  221. {
  222. hr = CheckpointFsmoOwnerTransfer(m_pSheet->GetBasePathsInfo());
  223. TRACE(_T("back from Checkpoint API, hr is %lx\n"), hr);
  224. if (FAILED(hr))
  225. {
  226. //
  227. // See if we are in native mode or mixed mode
  228. //
  229. BOOL bMixedMode = TRUE;
  230. CString szDomainRoot;
  231. m_pSheet->GetBasePathsInfo()->GetDefaultRootPath(szDomainRoot);
  232. if (!szDomainRoot.IsEmpty())
  233. {
  234. //
  235. // bind to the domain object
  236. //
  237. CComPtr<IADs> spDomainObj;
  238. hr = DSAdminOpenObject(szDomainRoot,
  239. IID_IADs,
  240. (void **) &spDomainObj,
  241. TRUE /*bServer*/);
  242. if (SUCCEEDED(hr))
  243. {
  244. //
  245. // retrieve the mixed node attribute
  246. //
  247. CComVariant Mixed;
  248. CComBSTR bsMixed(L"nTMixedDomain");
  249. spDomainObj->Get(bsMixed, &Mixed);
  250. bMixedMode = (BOOL)Mixed.bVal;
  251. }
  252. }
  253. if (bMixedMode)
  254. {
  255. if (ReportErrorEx(m_hWnd, IDS_CHANGE_FSMO_CHECKPOINT_FAILED, S_OK,
  256. MB_OKCANCEL | MB_ICONWARNING, NULL, 0) != IDOK)
  257. {
  258. return;
  259. }
  260. }
  261. else
  262. {
  263. if (ReportErrorEx(m_hWnd, IDS_CHANGE_FSMO_CHECKPOINT_FAILED_NATIVEMODE, S_OK,
  264. MB_OKCANCEL | MB_ICONWARNING, NULL, 0) != IDOK)
  265. {
  266. return;
  267. }
  268. }
  269. }
  270. }
  271. hr = GracefulFsmoOwnerTransfer(m_pSheet->GetBasePathsInfo(), m_fsmoType);
  272. }
  273. if (FAILED(hr))
  274. {
  275. if (!AllowForcedTransfer(hr))
  276. return;
  277. // try the forced transfer
  278. CWaitCursor wait;
  279. hr = ForcedFsmoOwnerTransfer(m_pSheet->GetBasePathsInfo(), m_fsmoType);
  280. }
  281. if (SUCCEEDED(hr))
  282. {
  283. m_szFsmoOwnerServerName = m_pSheet->GetBasePathsInfo()->GetServerName();
  284. _SetFsmoServerStatus(TRUE);
  285. ReportErrorEx(m_hWnd,IDS_CHANGE_FSMO_SUCCESS,S_OK,
  286. MB_OK, NULL, 0);
  287. }
  288. else
  289. {
  290. ReportErrorEx(m_hWnd, IDS_ERROR_CHANGE_FSMO_OWNER, hr,
  291. MB_OK | MB_ICONERROR, NULL, 0);
  292. }
  293. }
  294. void CFsmoPropertyPage::_SetFsmoServerStatus(BOOL bOnLine)
  295. {
  296. // set the FSMO owner server name
  297. if (m_szFsmoOwnerServerName.IsEmpty())
  298. {
  299. CString szError;
  300. szError.LoadString(IDS_FSMO_SERVER_ERROR);
  301. SetDlgItemText(IDC_EDIT_CURRENT_FSMO_DC, szError);
  302. }
  303. else
  304. {
  305. SetDlgItemText(IDC_EDIT_CURRENT_FSMO_DC, m_szFsmoOwnerServerName);
  306. }
  307. // set the status of the FSMO owner server
  308. m_fsmoServerState.SetToggleState(bOnLine);
  309. }
  310. void CFsmoPropertyPage::OnHelpInfo(HELPINFO * pHelpInfo )
  311. {
  312. TRACE(_T("OnHelpInfo: CtrlId = %d, ContextId = 0x%x\n"),
  313. pHelpInfo->iCtrlId, pHelpInfo->dwContextId);
  314. if (pHelpInfo->iCtrlId < 1) {
  315. return;
  316. }
  317. DWORD_PTR HelpArray = 0;
  318. switch (m_fsmoType)
  319. {
  320. case RID_POOL_FSMO:
  321. HelpArray = (DWORD_PTR)g_aHelpIDs_IDD_RID_FSMO_PAGE;
  322. break;
  323. case PDC_FSMO:
  324. HelpArray = (DWORD_PTR)g_aHelpIDs_IDD_PDC_FSMO_PAGE;
  325. break;
  326. case INFRASTUCTURE_FSMO:
  327. HelpArray = (DWORD_PTR)g_aHelpIDs_IDD_INFRA_FSMO_PAGE;
  328. break;
  329. };
  330. ::WinHelp((HWND)pHelpInfo->hItemHandle,
  331. DSADMIN_CONTEXT_HELP_FILE,
  332. HELP_WM_HELP,
  333. HelpArray);
  334. }
  335. void ChangeFormatParamOnString(CString& szFmt)
  336. {
  337. int nPos = szFmt.Find(L"%1");
  338. if (nPos == -1)
  339. return;
  340. szFmt.SetAt(nPos+1, L's');
  341. }
  342. BOOL CFsmoPropertyPage::AllowForcedTransfer(HRESULT hr)
  343. {
  344. BOOL bAllow = FALSE;
  345. PWSTR pszError = 0;
  346. StringErrorFromHr(hr, &pszError);
  347. // retrieve the DWORD error code
  348. DWORD dwErr = (hr & 0x0000FFFF);
  349. if ( (dwErr != ERROR_ACCESS_DENIED) &&
  350. ((m_fsmoType == PDC_FSMO) || (m_fsmoType == INFRASTUCTURE_FSMO)))
  351. {
  352. // allow forced, so ask
  353. CString szFmt, szMsg;
  354. szFmt.LoadString(IDS_CHANGE_FSMO_CONFIRMATION_FORCED);
  355. szMsg.Format(szFmt, pszError);
  356. CMoreInfoMessageBox dlg(m_hWnd, m_pSheet->GetIDisplayHelp(), TRUE);
  357. dlg.SetMessage(szMsg);
  358. dlg.SetURL((m_fsmoType == PDC_FSMO) ?
  359. DSADMIN_MOREINFO_PDC_FSMO_TOPIC :
  360. DSADMIN_MOREINFO_INFRASTUCTURE_FSMO_TOPIC);
  361. if (dlg.DoModal() == IDOK)
  362. bAllow = TRUE;
  363. }
  364. else
  365. {
  366. // warn only, no forced transfer option
  367. CString szFmt, szMsg;
  368. szFmt.LoadString(IDS_ERROR_CHANGE_FSMO_OWNER);
  369. // this format string has the replaceable parameter marked as %1
  370. // we need it changed into %s
  371. ChangeFormatParamOnString(szFmt);
  372. szMsg.Format(szFmt, pszError);
  373. CMoreInfoMessageBox dlg(m_hWnd, m_pSheet->GetIDisplayHelp(), FALSE);
  374. dlg.SetMessage(szMsg);
  375. dlg.SetURL(DSADMIN_MOREINFO_RID_POOL_FSMO_TOPIC);
  376. dlg.DoModal();
  377. }
  378. if (pszError)
  379. {
  380. delete[] pszError;
  381. pszError = 0;
  382. }
  383. return bAllow;
  384. }
  385. //////////////////////////////////////////////////////////////////
  386. // CFsmoPropertySheet
  387. int CALLBACK CFsmoPropertySheet::PropSheetCallBack(HWND hwndDlg,
  388. UINT uMsg,
  389. LPARAM)
  390. {
  391. switch (uMsg) {
  392. case PSCB_INITIALIZED:
  393. DWORD dwStyle = GetWindowLong (hwndDlg, GWL_EXSTYLE);
  394. dwStyle |= WS_EX_CONTEXTHELP;
  395. SetWindowLong (hwndDlg, GWL_EXSTYLE, dwStyle);
  396. break;
  397. }
  398. return 0;
  399. }
  400. CFsmoPropertySheet::CFsmoPropertySheet(MyBasePathsInfo* pInfo,
  401. HWND HWndParent,
  402. IDisplayHelp* pIDisplayHelp,
  403. LPCWSTR) :
  404. m_spIDisplayHelp(pIDisplayHelp), m_pInfo(pInfo),
  405. m_page1(this, RID_POOL_FSMO), m_page2(this, PDC_FSMO), m_page3(this, INFRASTUCTURE_FSMO)
  406. {
  407. // build the sheet title
  408. CString szTitle;
  409. szTitle.LoadString(IDS_FSMO_SHEET_TITLE);
  410. // delayed construction
  411. Construct(szTitle, CWnd::FromHandle(HWndParent));
  412. m_psh.dwFlags |= PSH_NOAPPLYNOW | PSH_USECALLBACK;
  413. m_psh.pfnCallback = PropSheetCallBack;
  414. AddPage(&m_page1);
  415. AddPage(&m_page2);
  416. AddPage(&m_page3);
  417. }