//++ // // Copyright (C) Microsoft Corporation, 1987 - 1999 // // Module Name: // // dsgetdc.c // // Abstract: // // Queries into network drivers // // Author: // // Anilth - 4-20-1998 // // Environment: // // User mode only. // Contains NT-specific code. // // Revision History: // //-- #include "precomp.h" #include "objbase.h" VOID PrintDsGetDcName(IN NETDIAG_RESULT *pResults, IN OUT PLIST_ENTRY plmsgOutput, IN PDOMAIN_CONTROLLER_INFOW DomainControllerInfo); NET_API_STATUS SetPrimaryGuid(IN GUID *GuidToSet); HRESULT DsGetDcTest(NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults) /*++ Routine Description: Ensure that we can find domain controllers Arguments: None. Return Value: TRUE: Test suceeded. FALSE: Test failed --*/ { NET_API_STATUS NetStatus; NET_API_STATUS LocalNetStatus; BOOL RetVal = TRUE; HRESULT hr = hrOK; LPTSTR pszDcType; PTESTED_DOMAIN pTestedDomain = (PTESTED_DOMAIN) pParams->pDomain; PDOMAIN_CONTROLLER_INFOW LocalDomainControllerInfo = NULL; //if the machine is a member machine or DC, DsGetDc Test will get called. //Otherwise, this test will be skipped pResults->DsGetDc.fPerformed = TRUE; //the DsGetDc test will be called for every domain, but we only want to initialize //the message list once. if(pResults->DsGetDc.lmsgOutput.Flink == NULL) InitializeListHead(&pResults->DsGetDc.lmsgOutput); PrintStatusMessage(pParams, 4, IDS_DSGETDC_STATUS_MSG); // // Find a generic DC // PrintStatusMessage(pParams, 4, IDS_DSGETDC_STATUS_DC); pszDcType = LoadAndAllocString(IDS_DCTYPE_DC); NetStatus = DoDsGetDcName( pParams, pResults, &pResults->DsGetDc.lmsgOutput, pTestedDomain, DS_DIRECTORY_SERVICE_PREFERRED, pszDcType, //_T("DC"), TRUE, &pTestedDomain->DcInfo ); Free(pszDcType); pTestedDomain->fTriedToFindDcInfo = TRUE; if ( NetStatus != NO_ERROR ) { hr = S_FALSE; goto Error; } // // Find a PDC // (Failure isn't fatal.) // PrintStatusMessage(pParams, 4, IDS_DSGETDC_STATUS_PDC); pszDcType = LoadAndAllocString(IDS_DCTYPE_PDC); LocalNetStatus = DoDsGetDcName(pParams, pResults, &pResults->DsGetDc.lmsgOutput, pTestedDomain, DS_PDC_REQUIRED, pszDcType, //_T("PDC"), FALSE, &LocalDomainControllerInfo ); Free(pszDcType); if ( LocalNetStatus == NO_ERROR ) { if ( LocalDomainControllerInfo != NULL ) { NetApiBufferFree( LocalDomainControllerInfo ); LocalDomainControllerInfo = NULL; } } // // Find an NT 5 DC // (Failure isn't fatal.) // PrintStatusMessage(pParams, 4, IDS_DSGETDC_STATUS_NT5DC); pszDcType = LoadAndAllocString(IDS_DCTYPE_W2K_DC); LocalNetStatus = DoDsGetDcName(pParams, pResults, &pResults->DsGetDc.lmsgOutput, pTestedDomain, DS_DIRECTORY_SERVICE_REQUIRED, pszDcType, //_T("Windows 2000 DC"), FALSE, &LocalDomainControllerInfo ); Free(pszDcType); if ( LocalNetStatus == NO_ERROR ) { if ( LocalDomainControllerInfo != NULL ) { NetApiBufferFree( LocalDomainControllerInfo ); LocalDomainControllerInfo = NULL; } } // // Ensure the returned domain GUID is the domain GUID stored in the LSA // if ( pTestedDomain == pResults->Global.pMemberDomain ) { if ( !IsEqualGUID( &pResults->Global.pPrimaryDomainInfo->DomainGuid, &NlDcZeroGuid ) && !IsEqualGUID( &pTestedDomain->DcInfo->DomainGuid, &NlDcZeroGuid ) && !IsEqualGUID( &pResults->Global.pPrimaryDomainInfo->DomainGuid, &pTestedDomain->DcInfo->DomainGuid ) ) { // Need to convert the two GUIDS WCHAR swzGuid1[64]; WCHAR swzGuid2[64]; StringFromGUID2(&pResults->Global.pPrimaryDomainInfo->DomainGuid, swzGuid1, DimensionOf(swzGuid1)); StringFromGUID2(&pTestedDomain->DcInfo->DomainGuid, swzGuid2, DimensionOf(swzGuid2)); // " [FATAL] Your machine thinks the domain GUID of domain '%ws' is\n '" // "' but \n '%ws' thinks it is\n '" AddMessageToList(&pResults->DsGetDc.lmsgOutput, Nd_Quiet, IDS_DSGETDC_FATAL_GUID, pResults->Global.pPrimaryDomainInfo->DomainNameFlat, swzGuid1, pTestedDomain->DcInfo->DomainControllerName, swzGuid2); hr = S_FALSE; // // Attempt to fix the problem. // if ( !pParams->fFixProblems ) { // "\nConsider running 'nettest /fix' to try to fix this problem\n" AddMessageToList( &pResults->DsGetDc.lmsgOutput, Nd_Quiet, IDS_DSGETDC_13206 ); } else { NetStatus = SetPrimaryGuid( &pTestedDomain->DcInfo->DomainGuid ); if ( NetStatus != NO_ERROR ) { if ( NetStatus == ERROR_ACCESS_DENIED ) { // "\nCannot fix domain GUID since you are not an administrator. Leave then rejoin the domain.\n" AddMessageToList( &pResults->DsGetDc.lmsgOutput, Nd_Quiet, IDS_DSGETDC_13207 ); } else { // " [FATAL] Failed to fix Domain Guid. [%s]\n" AddMessageToList( &pResults->DsGetDc.lmsgOutput, Nd_Quiet, IDS_DSGETDC_13208, NetStatusToString(NetStatus) ); } } else { // "\nFixed domain GUID. Reboot then run 'nettest' again to ensure everything is working.\n" AddMessageToList( &pResults->DsGetDc.lmsgOutput, Nd_Quiet, IDS_DSGETDC_13209 ); } } } } Error: //$REVIEW (nsun 10/05/98) CliffV deleted DCNameClose() //DCNameClose(); pResults->DsGetDc.hr = hr; return hr; } VOID PrintDsGetDcName( IN NETDIAG_RESULT *pResults, IN OUT PLIST_ENTRY plmsgOutput, IN PDOMAIN_CONTROLLER_INFOW DomainControllerInfo ) /*++ Routine Description: Prints the information returned from DsGetDcName Arguments: DomainControllerInfo - Information to print Return Value: None. --*/ { // " DC: %ws\n" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13210, DomainControllerInfo->DomainControllerName ); // " Address: %ws\n" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13211, DomainControllerInfo->DomainControllerAddress ); if ( !IsEqualGUID( &DomainControllerInfo->DomainGuid, &NlDcZeroGuid) ) { WCHAR swzGuid[64]; StringFromGUID2(&DomainControllerInfo->DomainGuid, swzGuid, DimensionOf(swzGuid)); // " Domain Guid . . . . . . : %ws\n" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13212, swzGuid); } if ( DomainControllerInfo->DomainName != NULL ) { // " Dom Name: %ws\n" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13214, DomainControllerInfo->DomainName ); } if ( DomainControllerInfo->DnsForestName != NULL ) { // " Forest Name: %ws\n" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13215, DomainControllerInfo->DnsForestName ); } if ( DomainControllerInfo->DcSiteName != NULL ) { // " Dc Site Name: %ws\n" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13216, DomainControllerInfo->DcSiteName ); } if ( DomainControllerInfo->ClientSiteName != NULL ) { // " Our Site Name: %ws\n" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13217, DomainControllerInfo->ClientSiteName ); } if ( DomainControllerInfo->Flags ) { ULONG LocalFlags = DomainControllerInfo->Flags; // " Flags:" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13218 ); if ( LocalFlags & DS_PDC_FLAG ) { // " PDC" AddMessageToList( plmsgOutput, Nd_Quiet, (LocalFlags & DS_DS_FLAG) ? IDS_DSGETDC_13219 : IDS_DSGETDC_NT4_PDC); LocalFlags &= ~DS_PDC_FLAG; } if ( LocalFlags & DS_GC_FLAG ) { //IDS_DSGETDC_13220 " GC" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13220); LocalFlags &= ~DS_GC_FLAG; } if ( LocalFlags & DS_DS_FLAG ) { //IDS_DSGETDC_13221 " DS" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13221); LocalFlags &= ~DS_DS_FLAG; } if ( LocalFlags & DS_KDC_FLAG ) { //IDS_DSGETDC_13222 " KDC" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13222); LocalFlags &= ~DS_KDC_FLAG; } if ( LocalFlags & DS_TIMESERV_FLAG ) { //IDS_DSGETDC_13223 " TIMESERV" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13223); LocalFlags &= ~DS_TIMESERV_FLAG; } if ( LocalFlags & DS_GOOD_TIMESERV_FLAG ) { //IDS_DSGETDC_13224 " GTIMESERV" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13224); LocalFlags &= ~DS_GOOD_TIMESERV_FLAG; } if ( LocalFlags & DS_WRITABLE_FLAG ) { //IDS_DSGETDC_13225 " WRITABLE" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13225); LocalFlags &= ~DS_WRITABLE_FLAG; } if ( LocalFlags & DS_DNS_CONTROLLER_FLAG ) { //IDS_DSGETDC_13226 " DNS_DC" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13226); LocalFlags &= ~DS_DNS_CONTROLLER_FLAG; } if ( LocalFlags & DS_DNS_DOMAIN_FLAG ) { //IDS_DSGETDC_13227 " DNS_DOMAIN" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13227); LocalFlags &= ~DS_DNS_DOMAIN_FLAG; } if ( LocalFlags & DS_DNS_FOREST_FLAG ) { //IDS_DSGETDC_13228 " DNS_FOREST" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13228); LocalFlags &= ~DS_DNS_FOREST_FLAG; } if ( LocalFlags & DS_CLOSEST_FLAG ) { //IDS_DSGETDC_13229 " CLOSE_SITE" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13229); LocalFlags &= ~DS_CLOSEST_FLAG; } if ( LocalFlags != 0 ) { //IDS_DSGETDC_13230 " 0x%lX" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13230, LocalFlags); } //IDS_DSGETDC_13231 "\n" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13231); } } NET_API_STATUS DoDsGetDcName(IN NETDIAG_PARAMS *pParams, IN OUT NETDIAG_RESULT *pResults, OUT PLIST_ENTRY plmsgOutput, IN PTESTED_DOMAIN pTestedDomain, IN DWORD Flags, IN LPTSTR pszDcType, IN BOOLEAN IsFatal, OUT PDOMAIN_CONTROLLER_INFOW *DomainControllerInfo ) /*++ Routine Description: Does a DsGetDcName Arguments: plmsgOutput - The message list to dump output pTestedDomain - Domain to test Flags - Flags to pass to DsGetDcName pszDcType - English description of Flags IsFatal - True if failure is fatal DomainControllerInfo - Return Domain Controller information Return Value: Status of the operation. --*/ { NET_API_STATUS NetStatus; PDOMAIN_CONTROLLER_INFOW LocalDomainControllerInfo = NULL; LPSTR Severity; // // Initialization // if ( IsFatal ) { Severity = "[FATAL]"; } else { Severity = "[WARNING]"; } if ( pParams->fReallyVerbose ) { // "\n Find %s in domain '%ws':\n" AddMessageToList( plmsgOutput, Nd_ReallyVerbose, IDS_DSGETDC_13232, pszDcType, pTestedDomain->PrintableDomainName ); } // // Find a DC in the domain. // Use the DsGetDcName built into nettest. // NetStatus = GetADc( pParams, pResults, plmsgOutput, // Commented out to port to Source Depot - smanda #ifdef SLM_TREE NettestDsGetDcNameW, #else DsGetDcNameW, #endif pTestedDomain, Flags, DomainControllerInfo ); if ( NetStatus != NO_ERROR ) { // " %s Cannot find %s in domain '%ws'. [%s]\n" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13233, Severity, pszDcType, pTestedDomain->PrintableDomainName, NetStatusToString(NetStatus)); if ( NetStatus == ERROR_NO_SUCH_DOMAIN ) { if ( Flags & DS_DIRECTORY_SERVICE_REQUIRED ) { // "\n This isn't a problem if domain '%ws' does not have any NT 5.0 DCs.\n" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13234, pTestedDomain->PrintableDomainName ); } else if ( Flags & DS_PDC_REQUIRED ) { PrintGuruMessage2(" If the PDC for domain '%ws' is up, ", TestedDomain->PrintableDomainName ); PrintGuru( 0, DSGETDC_GURU ); } else { PrintGuruMessage3(" If any %s for domain '%ws' is up, ", DcType, TestedDomain->PrintableDomainName ); PrintGuru( 0, DSGETDC_GURU ); } } else { PrintGuru( NetStatus, DSGETDC_GURU ); } // // If that worked, // try again through netlogon this time. // } else { if (pParams->fReallyVerbose ) { // " Found this %s in domain '%ws':\n" AddMessageToList( plmsgOutput, Nd_ReallyVerbose, IDS_DSGETDC_13235, pszDcType, pTestedDomain->PrintableDomainName ); PrintDsGetDcName( pResults, plmsgOutput, *DomainControllerInfo ); } else if ( pParams->fVerbose ) { // " Found %s '%ws' in domain '%ws'.\n" AddMessageToList( plmsgOutput, Nd_Verbose, IDS_DSGETDC_13236, pszDcType, (*DomainControllerInfo)->DomainControllerName, pTestedDomain->PrintableDomainName ); } if ( ((*DomainControllerInfo)->Flags & (DS_DS_FLAG|DS_KDC_FLAG)) == DS_DS_FLAG ) { // " %s: KDC is not running on NT 5 DC '%ws' in domain '%ws'." AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13237, Severity, (*DomainControllerInfo)->DomainControllerName, pTestedDomain->PrintableDomainName ); } // // If netlogon is running, // try it again using the netlogon service. // if ( pResults->Global.fNetlogonIsRunning ) { NetStatus = GetADc( pParams, pResults, plmsgOutput, DsGetDcNameW, pTestedDomain, Flags, &LocalDomainControllerInfo ); if ( NetStatus != NO_ERROR ) { // " %s: Netlogon cannot find %s in domain '%ws'. [%s]\n" AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13238, Severity, pszDcType, pTestedDomain->PrintableDomainName, NetStatusToString(NetStatus)); // // If that worked, // sanity check the returned DC. // } else { if ( (LocalDomainControllerInfo->Flags & (DS_DS_FLAG|DS_KDC_FLAG)) == DS_DS_FLAG ) { // " %s: KDC is not running on NT 5 DC '%ws' in domain '%ws'." AddMessageToList( plmsgOutput, Nd_Quiet, IDS_DSGETDC_13239, Severity, LocalDomainControllerInfo->DomainControllerName, pTestedDomain->PrintableDomainName ); } } } } if ( LocalDomainControllerInfo != NULL ) { NetApiBufferFree( LocalDomainControllerInfo ); LocalDomainControllerInfo = NULL; } return NetStatus; } NET_API_STATUS SetPrimaryGuid( IN GUID *GuidToSet ) /*++ Routine Description: Set the primary GUID to the specified value. Arguments: GuidToSet - Guid to set as the primary GUID Return Value: NET_API_STATUS - NERR_Success or reason for failure. --*/ { NET_API_STATUS NetStatus; NTSTATUS Status; LSA_HANDLE PolicyHandle = NULL; PPOLICY_DNS_DOMAIN_INFO PrimaryDomainInfo = NULL; OBJECT_ATTRIBUTES ObjAttributes; // // Open a handle to the LSA. // InitializeObjectAttributes( &ObjAttributes, NULL, 0L, NULL, NULL ); Status = LsaOpenPolicy( NULL, &ObjAttributes, POLICY_VIEW_LOCAL_INFORMATION | POLICY_TRUST_ADMIN, &PolicyHandle ); if (! NT_SUCCESS(Status)) { NetStatus = NetpNtStatusToApiStatus(Status); goto Cleanup; } // // Get the name of the primary domain from LSA // Status = LsaQueryInformationPolicy( PolicyHandle, PolicyDnsDomainInformation, (PVOID *) &PrimaryDomainInfo ); if (! NT_SUCCESS(Status)) { NetStatus = NetpNtStatusToApiStatus(Status); goto Cleanup; } // // Set the new GUID of the primary domain into the LSA // PrimaryDomainInfo->DomainGuid = *GuidToSet; Status = LsaSetInformationPolicy( PolicyHandle, PolicyDnsDomainInformation, (PVOID) PrimaryDomainInfo ); if (! NT_SUCCESS(Status)) { NetStatus = NetpNtStatusToApiStatus(Status); goto Cleanup; } NetStatus = NO_ERROR; Cleanup: if ( PrimaryDomainInfo != NULL ) { (void) LsaFreeMemory((PVOID) PrimaryDomainInfo); } if ( PolicyHandle != NULL ) { (void) LsaClose(PolicyHandle); } return NetStatus; } /*!-------------------------------------------------------------------------- DsGetDcGlobalPrint - Author: KennT ---------------------------------------------------------------------------*/ void DsGetDcGlobalPrint( NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults) { if (pParams->fVerbose || !FHrOK(pResults->DsGetDc.hr)) { PrintNewLine(pParams, 2); PrintTestTitleResult(pParams, IDS_DSGETDC_LONG, IDS_DSGETDC_SHORT, pResults->DsGetDc.fPerformed, pResults->DsGetDc.hr, 0); if (pParams->fReallyVerbose || !FHrOK(pResults->DsGetDc.hr)) PrintMessageList(pParams, &pResults->DsGetDc.lmsgOutput); } } /*!-------------------------------------------------------------------------- DsGetDcPerInterfacePrint - Author: KennT ---------------------------------------------------------------------------*/ void DsGetDcPerInterfacePrint( NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults, INTERFACE_RESULT *pInterfaceResults) { // no per-interface results } /*!-------------------------------------------------------------------------- DsGetDcCleanup - Author: KennT ---------------------------------------------------------------------------*/ void DsGetDcCleanup( NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults) { MessageListCleanUp(&pResults->DsGetDc.lmsgOutput); }