//+------------------------------------------------------------------------- // // Windows NT Directory Service Administration SnapIn // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1999 // // File: dssite.cpp // // Contents: DS App // // History: 04-nov-99 JeffJon Created // //-------------------------------------------------------------------------- #include "stdafx.h" #include "resource.h" #include "dsutil.h" #include "uiutil.h" #include "dssnap.h" #include "ntdsapi.h" #ifdef FIXUPDC FixupOptionsMsg g_FixupOptionsMsg[NUM_FIXUP_OPTIONS] = { {DSROLE_DC_FIXUP_ACCOUNT, IDS_FIXUP_ACCOUNT, FALSE}, {DSROLE_DC_FIXUP_ACCOUNT_PASSWORD, IDS_FIXUP_ACCOUNT_PASSWORD, TRUE}, {DSROLE_DC_FIXUP_ACCOUNT_TYPE, IDS_FIXUP_ACCOUNT_TYPE, TRUE}, {DSROLE_DC_FIXUP_TIME_SERVICE, IDS_FIXUP_TIME_SERVICE, FALSE}, {DSROLE_DC_FIXUP_DC_SERVICES, IDS_FIXUP_DC_SERVICES, FALSE}, {DSROLE_DC_FIXUP_FORCE_SYNC, IDS_FIXUP_FORCE_SYNC, TRUE} }; #endif // FIXUPDC #ifdef FIXUPDC // put back in RESOURCE.H if/when this is restored #define IDD_FIXUP_DC 239 #define IDC_FIXUP_DC_SERVER 265 #define IDC_FIXUP_DC_CHECK0 266 #define IDC_FIXUP_DC_CHECK1 267 #define IDC_FIXUP_DC_CHECK2 268 #define IDC_FIXUP_DC_CHECK3 269 #define IDC_FIXUP_DC_CHECK4 270 #define IDC_FIXUP_DC_CHECK5 271 #define IDM_GEN_TASK_FIXUP_DC 720 #define IDS_FIXUP_ITSELF 721 #define IDS_FIXUP_REPORT_ERROR 722 #define IDS_FIXUP_REPORT_SUCCESS 723 #define IDS_FIXUP_GEN_ERROR 724 #define IDS_FIXUP_ACCOUNT 725 #define IDS_FIXUP_ACCOUNT_PASSWORD 726 #define IDS_FIXUP_ACCOUNT_TYPE 727 #define IDS_FIXUP_TIME_SERVICE 728 #define IDS_FIXUP_DC_SERVICES 729 #define IDS_FIXUP_FORCE_SYNC 730 #define IDS_FIXUP_DC_SELECTION_WARNING 732 // put back in DSSNAP.RC if/when this is restored IDD_FIXUP_DC DIALOGEX 0, 0, 211, 163 STYLE DS_MODALFRAME | DS_CONTEXTHELP | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Repair Domain Controller" FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN LTEXT "Repair:",IDC_STATIC,12,14,33,8 EDITTEXT IDC_FIXUP_DC_SERVER,49,14,155,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER CONTROL "Repair Computer &Account",IDC_FIXUP_DC_CHECK0,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,18,35,151,10 CONTROL "Repair Computer Account &Password",IDC_FIXUP_DC_CHECK1, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,48,151,10 CONTROL "Repair Computer Account &Type",IDC_FIXUP_DC_CHECK2, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,61,151,10 CONTROL "&Synchronize Time Service",IDC_FIXUP_DC_CHECK3,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,18,74,151,10 CONTROL "&Reset Active Directory Services",IDC_FIXUP_DC_CHECK4, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,87,151,10 CONTROL "Synchronize Active &Directory",IDC_FIXUP_DC_CHECK5, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,100,151,10 DEFPUSHBUTTON "&OK",IDOK,29,143,50,14 PUSHBUTTON "&Cancel",IDCANCEL,108,143,50,14 END IDM_GEN_TASK_FIXUP_DC "Repair Domain Controller...\nRepair domain controller." 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?" IDS_FIXUP_REPORT_ERROR "The following operations succeeded:\n%2\nAn error occurred during the following operation:\n%3\nError:%1" IDS_FIXUP_REPORT_SUCCESS "The following operations succeeded:\n%1" IDS_FIXUP_GEN_ERROR "The repair of the domain controller was unsuccessful because:\n%1" IDS_FIXUP_ACCOUNT "\n Repair Computer Account." IDS_FIXUP_ACCOUNT_PASSWORD "\n Repair Computer Account Password." IDS_FIXUP_ACCOUNT_TYPE "\n Repair Computer Account Type." IDS_FIXUP_TIME_SERVICE "\n Synchronize Time Service." IDS_FIXUP_DC_SERVICES "\n Reset Active Directory Services." IDS_FIXUP_FORCE_SYNC "\n Synchronize Active Directory." IDS_FIXUP_DC_SELECTION_WARNING "Make a selection." HRESULT CDSComponentData::_FixupDC(LPCWSTR pwszPath) /*++ Routine Description: This function calls DsRoleFixDc() API to ssync and fixup local server against other DCs. Arguments: pwszPath: The LDAP Path of the local "server" object. We use this path to get the object, retrieve the server name and call the DsRoleFixDc() API. Return Value: HRESULT Report Error to user if any --*/ { // ISSUE-2002/04/05-artm Changes to CPasswordDlg impact this block of code. // I have changed CPasswordDlg class to store the password as an // encrypted string instead of a clear text string. Since this code is not // currently compiled and built JonN recommended I do not alter the code // to compile with the changes. // // The items that will need to be changed are: // a) Using an encrypted string variable to hold password received from // CPasswordDlg.DoModal(). // b) Access aforementioned password through the accessor methods of // CPasswordDlg. I have made the member fields private since this is // the only block of code that is impacted. // c) When passing the password to DsRoleFixDc() first decrypt the pwd // to a WCHAR* buffer scoped to the do {...} while() loop. Immediately // after the call to DsRoleFixDc() call password.DestroyClearTextCopy(). // This will ensure that the clear text copy is correctly zeroed out and // freed. Scoping the variable to the loop ensures that it will be // properly cleaned up. WARNING: password.GetClearTextCopy() can return // null on error (I think mainly from memory allocation failure, but not // sure). You need to think about if this should be handled, and if so, how. // d) Since the clear text copy is a WCHAR*, it is probably a good idea to call // password.Empty() to determine if NULL should be passed for the password. // e) May need to include a header file. #pragma message( __FILE__ ": CPasswordDlg class changed to use encrypted passwords. Investigate changes.") CThemeContextActivator activator; HRESULT hr = S_OK; CComPtr spIADs; hr = DSAdminOpenObject(pwszPath, IID_IADs, (PVOID *)&spIADs, TRUE /*bServer*/); if ( SUCCEEDED(hr) ) { // // retrieve the local server name // CComVariant var; hr = spIADs->Get(L"dNSHostName", &var); if ( SUCCEEDED(hr) ) { ASSERT((var.vt == VT_BSTR) && var.bstrVal && *(var.bstrVal)); LPWSTR lpszServer = var.bstrVal; CFixupDC dlgFixupDC; dlgFixupDC.m_strServer = lpszServer; if (IDCANCEL == dlgFixupDC.DoModal()) goto cleanup; // user cancelled the fixup process CWaitCursor wait; DWORD dwReturn = 0; BOOL fLocal = FALSE; CString strAccount = _T(""), strPassword = _T(""); DWORD dwOptions = 0; ULONG ulCompletedOps = 0, ulFailedOps = 0; for (int i=0; i spIADs; BOOL fSyncing = FALSE; CWaitCursor cwait; CComVariant var; LPWSTR lpszRunKCCServer = NULL; do { // false loop // Bind to "server" object hr = DSAdminOpenObject(pwszPath, IID_IADs, (PVOID *)&spIADs, TRUE /*bServer*/); if ( FAILED(hr) ) break; // retrieve the local server name hr = spIADs->Get(CComBSTR(L"dNSHostName"), &var); if ( FAILED(hr) ) break; if ((var.vt != VT_BSTR) || !(var.bstrVal) || !(*(var.bstrVal))) { ASSERT(FALSE); hr = E_FAIL; break; } lpszRunKCCServer = var.bstrVal; // now bind to the target DC Smart_DsHandle shDS; DWORD dwWinError = DsBind( lpszRunKCCServer, // DomainControllerAddress NULL, // DnsDomainName &shDS ); if (ERROR_SUCCESS != dwWinError) { hr = HRESULT_FROM_WIN32(dwWinError); break; } // Run the KCC synchronously on this DSA fSyncing = TRUE; dwWinError = DsReplicaConsistencyCheck( shDS, DS_KCC_TASKID_UPDATE_TOPOLOGY, 0 ); // synchronous, not DS_KCC_FLAG_ASYNC_OP if (ERROR_SUCCESS != dwWinError) { hr = HRESULT_FROM_WIN32(dwWinError); break; } } while (FALSE); // false loop if (FAILED(hr)) { (void) ReportErrorEx( m_hwnd, (fSyncing) ? IDS_RUN_KCC_1_FORCESYNC_ERROR : IDS_RUN_KCC_1_PARAMLOAD_ERROR, hr, MB_OK | MB_ICONEXCLAMATION, NULL, 0, IDS_RUN_KCC_TITLE ); } else { // JonN 3/30/00 // 26926: SITEREPL: Add popup after "Check Replication Topology" execution(DSLAB) LPCWSTR lpcwszDSADMINServer = NULL; if (NULL != GetBasePathsInfo()) { lpcwszDSADMINServer = GetBasePathsInfo()->GetServerName(); if ( !lpszRunKCCServer || !lpcwszDSADMINServer || !wcscmp( lpszRunKCCServer, lpcwszDSADMINServer ) ) lpcwszDSADMINServer = NULL; } PVOID apv[2] = { (PVOID)lpszRunKCCServer, (PVOID)lpcwszDSADMINServer }; (void) ReportMessageEx( m_hwnd, (NULL == lpcwszDSADMINServer) ? IDS_RUN_KCC_1_SUCCEEDED_LOCAL : IDS_RUN_KCC_2_SUCCEEDED_REMOTE, MB_OK | MB_ICONINFORMATION, apv, 2, IDS_RUN_KCC_TITLE ); } return hr; } // JonN 7/23/99 // 373806: Site&Svcs: Renaming an auto-generated connection should make it admin owned // RETURN TRUE iff rename should proceed, handles own errors BOOL CDSComponentData::RenameConnectionFixup(CDSCookie* pCookie) { ASSERT( NULL != pCookie ); CDSCookieInfoConnection* pextrainfo = (CDSCookieInfoConnection*)(pCookie->GetExtraInfo()); if ( (NULL == pextrainfo) || (pextrainfo->GetClass() != CDSCookieInfoBase::connection) || pextrainfo->m_fFRSConnection || !(NTDSCONN_OPT_IS_GENERATED & pextrainfo->m_nOptions) ) return TRUE; int nResponse = ReportMessageEx (m_hwnd, IDS_CONNECTION_RENAME_WARNING, MB_YESNO | MB_ICONWARNING); if (IDYES != nResponse) return FALSE; CString szPath; GetBasePathsInfo()->ComposeADsIPath(szPath, pCookie->GetPath()); CComPtr spDO; HRESULT hr = S_OK; do { // false loop hr = DSAdminOpenObject(szPath, IID_IDirectoryObject, (void **)&spDO, TRUE /*bServer*/); if ( FAILED(hr) ) break; PWSTR rgpwzAttrNames[] = {L"options"}; Smart_PADS_ATTR_INFO spAttrs; DWORD cAttrs = 1; hr = spDO->GetObjectAttributes(rgpwzAttrNames, 1, &spAttrs, &cAttrs); if (FAILED(hr)) break; if ( !(NTDSCONN_OPT_IS_GENERATED & spAttrs[0].pADsValues->Integer) ) break; spAttrs[0].pADsValues->Integer &= ~NTDSCONN_OPT_IS_GENERATED; spAttrs[0].dwControlCode = ADS_ATTR_UPDATE; ULONG cModified = 0; hr = spDO->SetObjectAttributes (spAttrs, 1, &cModified); } while (false); // false loop if (FAILED(hr)) { ReportErrorEx (m_hwnd, IDS_CONNECTION_RENAME_ERROR, hr, MB_OK|MB_ICONERROR, NULL, 0, 0, TRUE); return FALSE; } return TRUE; }