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.

442 lines
15 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Windows NT Directory Service Administration SnapIn
  4. //
  5. // Microsoft Windows
  6. // Copyright (C) Microsoft Corporation, 1992 - 1999
  7. //
  8. // File: dssite.cpp
  9. //
  10. // Contents: DS App
  11. //
  12. // History: 04-nov-99 JeffJon Created
  13. //
  14. //--------------------------------------------------------------------------
  15. #include "stdafx.h"
  16. #include "resource.h"
  17. #include "dsutil.h"
  18. #include "uiutil.h"
  19. #include "dssnap.h"
  20. #include "ntdsapi.h"
  21. #ifdef FIXUPDC
  22. FixupOptionsMsg g_FixupOptionsMsg[NUM_FIXUP_OPTIONS] = {
  23. {DSROLE_DC_FIXUP_ACCOUNT, IDS_FIXUP_ACCOUNT, FALSE},
  24. {DSROLE_DC_FIXUP_ACCOUNT_PASSWORD, IDS_FIXUP_ACCOUNT_PASSWORD, TRUE},
  25. {DSROLE_DC_FIXUP_ACCOUNT_TYPE, IDS_FIXUP_ACCOUNT_TYPE, TRUE},
  26. {DSROLE_DC_FIXUP_TIME_SERVICE, IDS_FIXUP_TIME_SERVICE, FALSE},
  27. {DSROLE_DC_FIXUP_DC_SERVICES, IDS_FIXUP_DC_SERVICES, FALSE},
  28. {DSROLE_DC_FIXUP_FORCE_SYNC, IDS_FIXUP_FORCE_SYNC, TRUE}
  29. };
  30. #endif // FIXUPDC
  31. #ifdef FIXUPDC
  32. // put back in RESOURCE.H if/when this is restored
  33. #define IDD_FIXUP_DC 239
  34. #define IDC_FIXUP_DC_SERVER 265
  35. #define IDC_FIXUP_DC_CHECK0 266
  36. #define IDC_FIXUP_DC_CHECK1 267
  37. #define IDC_FIXUP_DC_CHECK2 268
  38. #define IDC_FIXUP_DC_CHECK3 269
  39. #define IDC_FIXUP_DC_CHECK4 270
  40. #define IDC_FIXUP_DC_CHECK5 271
  41. #define IDM_GEN_TASK_FIXUP_DC 720
  42. #define IDS_FIXUP_ITSELF 721
  43. #define IDS_FIXUP_REPORT_ERROR 722
  44. #define IDS_FIXUP_REPORT_SUCCESS 723
  45. #define IDS_FIXUP_GEN_ERROR 724
  46. #define IDS_FIXUP_ACCOUNT 725
  47. #define IDS_FIXUP_ACCOUNT_PASSWORD 726
  48. #define IDS_FIXUP_ACCOUNT_TYPE 727
  49. #define IDS_FIXUP_TIME_SERVICE 728
  50. #define IDS_FIXUP_DC_SERVICES 729
  51. #define IDS_FIXUP_FORCE_SYNC 730
  52. #define IDS_FIXUP_DC_SELECTION_WARNING 732
  53. // put back in DSSNAP.RC if/when this is restored
  54. IDD_FIXUP_DC DIALOGEX 0, 0, 211, 163
  55. STYLE DS_MODALFRAME | DS_CONTEXTHELP | WS_POPUP | WS_CAPTION | WS_SYSMENU
  56. CAPTION "Repair Domain Controller"
  57. FONT 8, "MS Shell Dlg", 0, 0, 0x1
  58. BEGIN
  59. LTEXT "Repair:",IDC_STATIC,12,14,33,8
  60. EDITTEXT IDC_FIXUP_DC_SERVER,49,14,155,12,ES_AUTOHSCROLL |
  61. ES_READONLY | NOT WS_BORDER
  62. CONTROL "Repair Computer &Account",IDC_FIXUP_DC_CHECK0,"Button",
  63. BS_AUTOCHECKBOX | WS_TABSTOP,18,35,151,10
  64. CONTROL "Repair Computer Account &Password",IDC_FIXUP_DC_CHECK1,
  65. "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,48,151,10
  66. CONTROL "Repair Computer Account &Type",IDC_FIXUP_DC_CHECK2,
  67. "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,61,151,10
  68. CONTROL "&Synchronize Time Service",IDC_FIXUP_DC_CHECK3,"Button",
  69. BS_AUTOCHECKBOX | WS_TABSTOP,18,74,151,10
  70. CONTROL "&Reset Active Directory Services",IDC_FIXUP_DC_CHECK4,
  71. "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,87,151,10
  72. CONTROL "Synchronize Active &Directory",IDC_FIXUP_DC_CHECK5,
  73. "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,100,151,10
  74. DEFPUSHBUTTON "&OK",IDOK,29,143,50,14
  75. PUSHBUTTON "&Cancel",IDCANCEL,108,143,50,14
  76. END
  77. IDM_GEN_TASK_FIXUP_DC "Repair Domain Controller...\nRepair domain controller."
  78. IDS_FIXUP_ITSELF "No other domain controllers in the domain can be contacted. Do you want to repair domain controller %1\nusing its local copy of the directory information?"
  79. IDS_FIXUP_REPORT_ERROR "The following operations succeeded:\n%2\nAn error occurred during the following operation:\n%3\nError:%1"
  80. IDS_FIXUP_REPORT_SUCCESS "The following operations succeeded:\n%1"
  81. IDS_FIXUP_GEN_ERROR "The repair of the domain controller was unsuccessful because:\n%1"
  82. IDS_FIXUP_ACCOUNT "\n Repair Computer Account."
  83. IDS_FIXUP_ACCOUNT_PASSWORD "\n Repair Computer Account Password."
  84. IDS_FIXUP_ACCOUNT_TYPE "\n Repair Computer Account Type."
  85. IDS_FIXUP_TIME_SERVICE "\n Synchronize Time Service."
  86. IDS_FIXUP_DC_SERVICES "\n Reset Active Directory Services."
  87. IDS_FIXUP_FORCE_SYNC "\n Synchronize Active Directory."
  88. IDS_FIXUP_DC_SELECTION_WARNING "Make a selection."
  89. HRESULT CDSComponentData::_FixupDC(LPCWSTR pwszPath)
  90. /*++
  91. Routine Description:
  92. This function calls DsRoleFixDc() API to ssync and fixup
  93. local server against other DCs.
  94. Arguments:
  95. pwszPath: The LDAP Path of the local "server" object.
  96. We use this path to get the object, retrieve the server name
  97. and call the DsRoleFixDc() API.
  98. Return Value:
  99. HRESULT
  100. Report Error to user if any
  101. --*/
  102. {
  103. // ISSUE-2002/04/05-artm Changes to CPasswordDlg impact this block of code.
  104. // I have changed CPasswordDlg class to store the password as an
  105. // encrypted string instead of a clear text string. Since this code is not
  106. // currently compiled and built JonN recommended I do not alter the code
  107. // to compile with the changes.
  108. //
  109. // The items that will need to be changed are:
  110. // a) Using an encrypted string variable to hold password received from
  111. // CPasswordDlg.DoModal().
  112. // b) Access aforementioned password through the accessor methods of
  113. // CPasswordDlg. I have made the member fields private since this is
  114. // the only block of code that is impacted.
  115. // c) When passing the password to DsRoleFixDc() first decrypt the pwd
  116. // to a WCHAR* buffer scoped to the do {...} while() loop. Immediately
  117. // after the call to DsRoleFixDc() call password.DestroyClearTextCopy().
  118. // This will ensure that the clear text copy is correctly zeroed out and
  119. // freed. Scoping the variable to the loop ensures that it will be
  120. // properly cleaned up. WARNING: password.GetClearTextCopy() can return
  121. // null on error (I think mainly from memory allocation failure, but not
  122. // sure). You need to think about if this should be handled, and if so, how.
  123. // d) Since the clear text copy is a WCHAR*, it is probably a good idea to call
  124. // password.Empty() to determine if NULL should be passed for the password.
  125. // e) May need to include a header file.
  126. #pragma message( __FILE__ ": CPasswordDlg class changed to use encrypted passwords. Investigate changes.")
  127. CThemeContextActivator activator;
  128. HRESULT hr = S_OK;
  129. CComPtr<IADs> spIADs;
  130. hr = DSAdminOpenObject(pwszPath,
  131. IID_IADs,
  132. (PVOID *)&spIADs,
  133. TRUE /*bServer*/);
  134. if ( SUCCEEDED(hr) ) {
  135. //
  136. // retrieve the local server name
  137. //
  138. CComVariant var;
  139. hr = spIADs->Get(L"dNSHostName", &var);
  140. if ( SUCCEEDED(hr) )
  141. {
  142. ASSERT((var.vt == VT_BSTR) && var.bstrVal && *(var.bstrVal));
  143. LPWSTR lpszServer = var.bstrVal;
  144. CFixupDC dlgFixupDC;
  145. dlgFixupDC.m_strServer = lpszServer;
  146. if (IDCANCEL == dlgFixupDC.DoModal())
  147. goto cleanup; // user cancelled the fixup process
  148. CWaitCursor wait;
  149. DWORD dwReturn = 0;
  150. BOOL fLocal = FALSE;
  151. CString strAccount = _T(""), strPassword = _T("");
  152. DWORD dwOptions = 0;
  153. ULONG ulCompletedOps = 0, ulFailedOps = 0;
  154. for (int i=0; i<NUM_FIXUP_OPTIONS; i++) {
  155. if (dlgFixupDC.m_bCheck[i])
  156. dwOptions |= g_FixupOptionsMsg[i].dwOption;
  157. }
  158. //
  159. // call DsRoleFixDc() API to ssync and fixup the local server
  160. //
  161. do {
  162. dwReturn = DsRoleFixDc(
  163. lpszServer,
  164. (fLocal ? lpszServer : NULL),
  165. (strAccount.IsEmpty() ? NULL : (LPCWSTR)strAccount),
  166. (strAccount.IsEmpty() ? NULL : (LPCWSTR)strPassword),
  167. dwOptions,
  168. &ulCompletedOps,
  169. &ulFailedOps
  170. );
  171. if (ERROR_NO_SUCH_DOMAIN == dwReturn) {
  172. //
  173. // lpszServer is the only DC found in the domain,
  174. // ask if he wants to ssync and fixup the local server against itself
  175. //
  176. PVOID apv[1] = {(PVOID)lpszServer};
  177. if (IDNO == ReportMessageEx(m_hwnd, IDS_FIXUP_ITSELF, MB_YESNO | MB_ICONWARNING, apv, 1) )
  178. goto cleanup; // user cancelled the fixup process
  179. fLocal = TRUE;
  180. } else if (ERROR_ACCESS_DENIED == dwReturn) {
  181. //
  182. // connection failed
  183. // prompt for username and password
  184. //
  185. CPasswordDlg dlgPassword;
  186. if (IDCANCEL == dlgPassword.DoModal())
  187. goto cleanup; // user cancelled the fixup process
  188. strAccount = dlgPassword.m_strUserName;
  189. strPassword = dlgPassword.m_strPassword;
  190. } else {
  191. // either ERROR_SUCCESS or some other error happened
  192. break;
  193. }
  194. } while (TRUE);
  195. //
  196. // report succeeded/failed operations to user
  197. //
  198. CString strCompletedOps = _T(""), strFailedOps = _T("");
  199. CString strMsg;
  200. for (i=0; i<NUM_FIXUP_OPTIONS; i++) {
  201. if (ulCompletedOps & g_FixupOptionsMsg[i].dwOption) {
  202. strMsg.LoadString(g_FixupOptionsMsg[i].nMsgID);
  203. strCompletedOps += strMsg;
  204. }
  205. if (ulFailedOps & g_FixupOptionsMsg[i].dwOption) {
  206. strMsg.LoadString(g_FixupOptionsMsg[i].nMsgID);
  207. strFailedOps += strMsg;
  208. }
  209. }
  210. PVOID apv[2];
  211. apv[0] = (PVOID)(LPCWSTR)strCompletedOps;
  212. apv[1] = (PVOID)(LPCWSTR)strFailedOps;
  213. if (dwReturn != ERROR_SUCCESS) {
  214. ReportErrorEx(m_hwnd, IDS_FIXUP_REPORT_ERROR, dwReturn,
  215. MB_OK | MB_ICONINFORMATION, apv, 2, 0, FALSE);
  216. } else {
  217. ReportMessageEx(m_hwnd, IDS_FIXUP_REPORT_SUCCESS,
  218. MB_OK | MB_ICONINFORMATION, apv, 1);
  219. }
  220. } // Get()
  221. } // DSAdminOpenObject()
  222. if (FAILED(hr))
  223. ReportErrorEx(m_hwnd, IDS_FIXUP_GEN_ERROR, hr,
  224. MB_OK | MB_ICONINFORMATION, NULL, 0, 0);
  225. cleanup:
  226. return hr;
  227. }
  228. #endif // FIXUPDC
  229. HRESULT CDSComponentData::_RunKCC(LPCWSTR pwszPath)
  230. /*++
  231. Routine Description:
  232. This function calls DsReplicaConsistencyCheck()
  233. to force the KCC to recheck topology immediately.
  234. Arguments:
  235. pwszPath: The LDAP Path of the local "server" object.
  236. We use this path to get the object, retrieve the server name
  237. and call the DsReplicaConsistencyCheck() API.
  238. Return Value:
  239. HRESULT
  240. Report Error to user if any
  241. --*/
  242. {
  243. HRESULT hr = S_OK;
  244. CComPtr<IADs> spIADs;
  245. BOOL fSyncing = FALSE;
  246. CWaitCursor cwait;
  247. CComVariant var;
  248. LPWSTR lpszRunKCCServer = NULL;
  249. do { // false loop
  250. // Bind to "server" object
  251. hr = DSAdminOpenObject(pwszPath,
  252. IID_IADs,
  253. (PVOID *)&spIADs,
  254. TRUE /*bServer*/);
  255. if ( FAILED(hr) )
  256. break;
  257. // retrieve the local server name
  258. hr = spIADs->Get(CComBSTR(L"dNSHostName"), &var);
  259. if ( FAILED(hr) )
  260. break;
  261. if ((var.vt != VT_BSTR) || !(var.bstrVal) || !(*(var.bstrVal)))
  262. {
  263. ASSERT(FALSE);
  264. hr = E_FAIL;
  265. break;
  266. }
  267. lpszRunKCCServer = var.bstrVal;
  268. // now bind to the target DC
  269. Smart_DsHandle shDS;
  270. DWORD dwWinError = DsBind( lpszRunKCCServer, // DomainControllerAddress
  271. NULL, // DnsDomainName
  272. &shDS );
  273. if (ERROR_SUCCESS != dwWinError)
  274. {
  275. hr = HRESULT_FROM_WIN32(dwWinError);
  276. break;
  277. }
  278. // Run the KCC synchronously on this DSA
  279. fSyncing = TRUE;
  280. dwWinError = DsReplicaConsistencyCheck(
  281. shDS,
  282. DS_KCC_TASKID_UPDATE_TOPOLOGY,
  283. 0 ); // synchronous, not DS_KCC_FLAG_ASYNC_OP
  284. if (ERROR_SUCCESS != dwWinError)
  285. {
  286. hr = HRESULT_FROM_WIN32(dwWinError);
  287. break;
  288. }
  289. } while (FALSE); // false loop
  290. if (FAILED(hr))
  291. {
  292. (void) ReportErrorEx( m_hwnd,
  293. (fSyncing) ? IDS_RUN_KCC_1_FORCESYNC_ERROR
  294. : IDS_RUN_KCC_1_PARAMLOAD_ERROR,
  295. hr,
  296. MB_OK | MB_ICONEXCLAMATION,
  297. NULL,
  298. 0,
  299. IDS_RUN_KCC_TITLE );
  300. } else {
  301. // JonN 3/30/00
  302. // 26926: SITEREPL: Add popup after "Check Replication Topology" execution(DSLAB)
  303. LPCWSTR lpcwszDSADMINServer = NULL;
  304. if (NULL != GetBasePathsInfo())
  305. {
  306. lpcwszDSADMINServer = GetBasePathsInfo()->GetServerName();
  307. if ( !lpszRunKCCServer || !lpcwszDSADMINServer || !wcscmp( lpszRunKCCServer, lpcwszDSADMINServer ) )
  308. lpcwszDSADMINServer = NULL;
  309. }
  310. PVOID apv[2] = { (PVOID)lpszRunKCCServer, (PVOID)lpcwszDSADMINServer };
  311. (void) ReportMessageEx( m_hwnd,
  312. (NULL == lpcwszDSADMINServer)
  313. ? IDS_RUN_KCC_1_SUCCEEDED_LOCAL
  314. : IDS_RUN_KCC_2_SUCCEEDED_REMOTE,
  315. MB_OK | MB_ICONINFORMATION,
  316. apv,
  317. 2,
  318. IDS_RUN_KCC_TITLE );
  319. }
  320. return hr;
  321. }
  322. // JonN 7/23/99
  323. // 373806: Site&Svcs: Renaming an auto-generated connection should make it admin owned
  324. // RETURN TRUE iff rename should proceed, handles own errors
  325. BOOL CDSComponentData::RenameConnectionFixup(CDSCookie* pCookie)
  326. {
  327. ASSERT( NULL != pCookie );
  328. CDSCookieInfoConnection* pextrainfo =
  329. (CDSCookieInfoConnection*)(pCookie->GetExtraInfo());
  330. if ( (NULL == pextrainfo)
  331. || (pextrainfo->GetClass() != CDSCookieInfoBase::connection)
  332. || pextrainfo->m_fFRSConnection
  333. || !(NTDSCONN_OPT_IS_GENERATED & pextrainfo->m_nOptions)
  334. )
  335. return TRUE;
  336. int nResponse = ReportMessageEx (m_hwnd, IDS_CONNECTION_RENAME_WARNING,
  337. MB_YESNO | MB_ICONWARNING);
  338. if (IDYES != nResponse)
  339. return FALSE;
  340. CString szPath;
  341. GetBasePathsInfo()->ComposeADsIPath(szPath, pCookie->GetPath());
  342. CComPtr<IDirectoryObject> spDO;
  343. HRESULT hr = S_OK;
  344. do { // false loop
  345. hr = DSAdminOpenObject(szPath,
  346. IID_IDirectoryObject,
  347. (void **)&spDO,
  348. TRUE /*bServer*/);
  349. if ( FAILED(hr) )
  350. break;
  351. PWSTR rgpwzAttrNames[] = {L"options"};
  352. Smart_PADS_ATTR_INFO spAttrs;
  353. DWORD cAttrs = 1;
  354. hr = spDO->GetObjectAttributes(rgpwzAttrNames, 1, &spAttrs, &cAttrs);
  355. if (FAILED(hr))
  356. break;
  357. if ( !(NTDSCONN_OPT_IS_GENERATED & spAttrs[0].pADsValues->Integer) )
  358. break;
  359. spAttrs[0].pADsValues->Integer &= ~NTDSCONN_OPT_IS_GENERATED;
  360. spAttrs[0].dwControlCode = ADS_ATTR_UPDATE;
  361. ULONG cModified = 0;
  362. hr = spDO->SetObjectAttributes (spAttrs, 1, &cModified);
  363. } while (false); // false loop
  364. if (FAILED(hr)) {
  365. ReportErrorEx (m_hwnd, IDS_CONNECTION_RENAME_ERROR, hr,
  366. MB_OK|MB_ICONERROR, NULL, 0, 0, TRUE);
  367. return FALSE;
  368. }
  369. return TRUE;
  370. }