windows-nt/Source/XPSP1/NT/net/diagnostics/netdiag/member.c

586 lines
19 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
//++
//
// Copyright (C) Microsoft Corporation, 1987 - 1999
//
// Module Name:
//
// member.c
//
// Abstract:
//
// Queries into network drivers
//
// Author:
//
// Anilth - 4-20-1998
//
// Environment:
//
// User mode only.
// Contains NT-specific code.
//
// Revision History:
//
//--
#include "precomp.h"
#undef IsEqualGUID
#include "objbase.h"
#include "regutil.h"
#include "strings.h"
const WCHAR c_wszUserDnsDomain[] = L"USERDNSDOMAIN";
BOOL IsSysVolReady(NETDIAG_PARAMS* pParams);
/*!--------------------------------------------------------------------------
MemberTest
Determine the machines role and membership.
Arguments:
None.
Return Value:
TRUE: Test suceeded.
FALSE: Test failed
Author: KennT
---------------------------------------------------------------------------*/
HRESULT MemberTest(NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
{
PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pPrimaryDomain = NULL;
DWORD dwErr;
NTSTATUS Status;
DWORD LogonServerLength;
WCHAR swzLogonServer[MAX_PATH+1];
int iBuildNo;
BOOL fDomain; // TRUE if domain, FALSE is workgroup
LSA_HANDLE PolicyHandle = NULL;
PPOLICY_DNS_DOMAIN_INFO pPolicyDomainInfo = NULL;
OBJECT_ATTRIBUTES ObjAttributes;
PrintStatusMessage(pParams,0, IDS_MEMBER_STATUS_MSG);
//
// Get the build number of this machine
//
if (pResults->Global.pszCurrentBuildNumber &&
(pResults->Global.pszCurrentBuildNumber[0] == 0))
{
PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
PrintStatusMessage(pParams,0, IDS_MEMBER_CANNOT_DETERMINE_BUILD);
pResults->Global.hrMemberTestResult = E_FAIL;
return E_FAIL;
}
iBuildNo = _ttoi( pResults->Global.pszCurrentBuildNumber );
// Assmume that the test has succeeded
pResults->Global.hrMemberTestResult = hrOK;
//
// Get the name of the domain this machine is a member of
//
dwErr = DsRoleGetPrimaryDomainInformation(
NULL, // local call
DsRolePrimaryDomainInfoBasic,
(PBYTE *) &pPrimaryDomain);
pResults->Global.pPrimaryDomainInfo = pPrimaryDomain;
if (dwErr != NO_ERROR)
{
PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
PrintStatusMessage(pParams,0, IDS_MEMBER_CANNOT_DETERMINE_DOMAIN);
pResults->Global.hrMemberTestResult = E_FAIL;
goto Cleanup;
}
//
// Handle being a member of a domain
//
if ( pPrimaryDomain->MachineRole != DsRole_RoleStandaloneWorkstation &&
pPrimaryDomain->MachineRole != DsRole_RoleStandaloneServer )
{
//
// Ensure the netlogon service is running.
//
dwErr = IsServiceStarted( _T("Netlogon") );
if ( dwErr != NO_ERROR )
{
PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
PrintStatusMessage(pParams,0, IDS_MEMBER_NETLOGON_NOT_RUNNING);
}
else
{
pResults->Global.fNetlogonIsRunning = TRUE;
}
//
// Save the name of this domain as a domain to test.
// Do NOT free this up. This will get freed up
// by the code that frees up the list of domains.
pResults->Global.pMemberDomain = AddTestedDomain( pParams,
pResults,
pPrimaryDomain->DomainNameFlat,
pPrimaryDomain->DomainNameDns,
TRUE );
if (pResults->Global.pMemberDomain == NULL)
{
PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
pResults->Global.hrMemberTestResult = S_FALSE;
goto Cleanup;
}
//
// Get the SID of the domain we're a member of
//
InitializeObjectAttributes(
&ObjAttributes,
NULL,
0L,
NULL,
NULL
);
Status = LsaOpenPolicy(
NULL,
&ObjAttributes,
POLICY_VIEW_LOCAL_INFORMATION,
&PolicyHandle );
if (! NT_SUCCESS(Status))
{
PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
PrintDebugSz(pParams, 0, _T(" [FATAL] Member: Cannot LsaOpenPolicy."));
pResults->Global.hrMemberTestResult = S_FALSE;
goto Cleanup;
}
Status = LsaQueryInformationPolicy(
PolicyHandle,
PolicyDnsDomainInformation,
(PVOID *) &pPolicyDomainInfo
);
if (! NT_SUCCESS(Status))
{
PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
if (pParams->fDebugVerbose)
PrintDebugSz(pParams, 0, _T(" [FATAL] Member: Cannot LsaQueryInformationPolicy (PolicyDnsDomainInformation).") );
pResults->Global.hrMemberTestResult = S_FALSE;
goto Cleanup;
}
if ( pPolicyDomainInfo->Sid == NULL )
{
PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
// IDS_MEMBER_11206 " [FATAL] Member: Cannot LsaQueryInformationPolicy has no domain sid."
PrintDebug(pParams, 0, IDS_MEMBER_11206 );
pResults->Global.hrMemberTestResult = S_FALSE;
goto Cleanup;
}
//
// Save the domain sid for other tests
//
pResults->Global.pMemberDomain->DomainSid =
Malloc(RtlLengthSid(pPolicyDomainInfo->Sid));
if (pResults->Global.pMemberDomain->DomainSid == NULL)
{
PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
// IDS_MEMBER_11207 " Member: Out of memory\n"
PrintDebug(pParams, 0, IDS_MEMBER_11207);
pResults->Global.hrMemberTestResult = S_FALSE;
goto Cleanup;
}
RtlCopyMemory( pResults->Global.pMemberDomain->DomainSid,
pPolicyDomainInfo->Sid,
RtlLengthSid( pPolicyDomainInfo->Sid ) );
}
//Bug 293635, check whether system volume is ready if the machine is a DC
if (DsRole_RoleBackupDomainController == pPrimaryDomain->MachineRole ||
DsRole_RolePrimaryDomainController == pPrimaryDomain->MachineRole)
{
pResults->Global.fSysVolNotReady = !IsSysVolReady(pParams);
if (pResults->Global.fSysVolNotReady)
pResults->Global.hrMemberTestResult = S_FALSE;
}
//
// Get the name of the logged on user.
//
Status = LsaGetUserName( &pResults->Global.pLogonUser,
&pResults->Global.pLogonDomainName );
if ( !NT_SUCCESS(Status))
{
PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
PrintStatusMessage(pParams,0, IDS_MEMBER_UNKNOWN_LOGON);
pResults->Global.hrMemberTestResult = S_FALSE;
goto Cleanup;
}
//
// If we're not logged onto a local account,
// add the logon domain to the list of tested domains
//
if ( _wcsicmp( pResults->Global.swzNetBiosName,
pResults->Global.pLogonDomainName->Buffer ) != 0 )
{
LPWSTR pwszLogonDomainDnsName = NULL;
DWORD cchLogonDomainDnsName = 0;
cchLogonDomainDnsName = GetEnvironmentVariableW(c_wszUserDnsDomain,
NULL,
0);
if (cchLogonDomainDnsName)
{
pwszLogonDomainDnsName = Malloc(sizeof(WCHAR) * cchLogonDomainDnsName);
ZeroMemory(pwszLogonDomainDnsName, sizeof(WCHAR) * cchLogonDomainDnsName);
cchLogonDomainDnsName = GetEnvironmentVariableW(c_wszUserDnsDomain,
pwszLogonDomainDnsName,
cchLogonDomainDnsName);
}
// Save the name of this domain as a domain to test.
// ------------------------------------------------------------
if (cchLogonDomainDnsName && pwszLogonDomainDnsName && lstrlenW(pwszLogonDomainDnsName))
{
pResults->Global.pLogonDomain = AddTestedDomain( pParams, pResults,
pResults->Global.pLogonDomainName->Buffer,
pwszLogonDomainDnsName,
FALSE );
}
else
{
pResults->Global.pLogonDomain = AddTestedDomain( pParams, pResults,
pResults->Global.pLogonDomainName->Buffer,
NULL,
FALSE );
}
if (pwszLogonDomainDnsName)
Free(pwszLogonDomainDnsName);
if ( pResults->Global.pLogonDomain == NULL )
{
PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
pResults->Global.hrMemberTestResult = S_FALSE;
goto Cleanup;
}
}
//
// Get the name of the logon server.
//
LogonServerLength = GetEnvironmentVariableW(
L"LOGONSERVER",
swzLogonServer,
DimensionOf(swzLogonServer));
if ( LogonServerLength != 0 )
{
//
// If the caller was supposed to logon to a domain,
// and this isn't a DC,
// see if the user logged on with cached credentials.
//
if ( pResults->Global.pLogonDomain != NULL &&
pPrimaryDomain->MachineRole != DsRole_RoleBackupDomainController &&
pPrimaryDomain->MachineRole != DsRole_RolePrimaryDomainController ) {
LPWSTR pswzLogonServer;
if ( swzLogonServer[0] == L'\\' && swzLogonServer[1] == L'\\')
{
pswzLogonServer = &swzLogonServer[2];
}
else
{
pswzLogonServer = &swzLogonServer[0];
}
pResults->Global.pswzLogonServer = _wcsdup(swzLogonServer);
if ( _wcsicmp( pResults->Global.swzNetBiosName, pswzLogonServer ) == 0 )
{
pResults->Global.fLogonWithCachedCredentials = TRUE;
}
}
}
if (pPrimaryDomain->DomainNameFlat == NULL)
{
// the NetBIOS name is not specified
if (FHrSucceeded(pResults->Global.hrMemberTestResult))
pResults->Global.hrMemberTestResult = S_FALSE;
}
PrintStatusMessage(pParams,0, IDS_GLOBAL_PASS_NL);
Cleanup:
if ( pPolicyDomainInfo != NULL ) {
(void) LsaFreeMemory((PVOID) pPolicyDomainInfo);
}
if ( PolicyHandle != NULL ) {
(void) LsaClose(PolicyHandle);
}
return pResults->Global.hrMemberTestResult;
}
//Check if System Volume is ready
//Author: NSun
BOOL IsSysVolReady(NETDIAG_PARAMS* pParams)
{
DWORD dwData = 1;
DWORD dwSize = sizeof(dwData);
LONG lRet;
BOOL fRetVal = TRUE;
HKEY hkeyNetLogonParams = NULL;
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
c_szRegNetLogonParams,
0,
KEY_READ,
&hkeyNetLogonParams);
if (ERROR_SUCCESS == lRet)
{
//it's ok that the SysVolReady value doesn't exist
if (ReadRegistryDword(hkeyNetLogonParams,
c_szRegSysVolReady,
&dwData))
{
if (0 == dwData)
fRetVal = FALSE;
}
RegCloseKey(hkeyNetLogonParams);
}
else
PrintDebugSz(pParams, 0, _T("Failed to open the registry of NetLogon parameters.\n"));
return fRetVal;
}
/*!--------------------------------------------------------------------------
MemberGlobalPrint
-
Author: KennT
---------------------------------------------------------------------------*/
void MemberGlobalPrint(IN NETDIAG_PARAMS *pParams,
IN OUT NETDIAG_RESULT *pResults)
{
PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pPrimaryDomain = NULL;
BOOL fDomain = TRUE;
TCHAR szName[256];
int ids;
if (pParams->fVerbose || !FHrOK(pResults->Global.hrMemberTestResult))
{
PrintNewLine(pParams, 2);
PrintTestTitleResult(pParams, IDS_MEMBER_LONG, IDS_MEMBER_SHORT, TRUE,
pResults->Global.hrMemberTestResult, 0);
}
pPrimaryDomain = pResults->Global.pPrimaryDomainInfo;
if (!pPrimaryDomain)
goto L_ERROR;
//Bug 293635, check whether system volume is ready if the machine is a DC
if (pResults->Global.fSysVolNotReady &&
(DsRole_RoleBackupDomainController == pPrimaryDomain->MachineRole ||
DsRole_RolePrimaryDomainController == pPrimaryDomain->MachineRole))
{
PrintMessage(pParams, IDS_MEMBER_SYSVOL_NOT_READY);
}
if (pParams->fReallyVerbose)
//IDS_MEMBER_11208 " Machine is a: "
PrintMessage(pParams, IDS_MEMBER_11208 );
switch ( pPrimaryDomain->MachineRole )
{
case DsRole_RoleStandaloneWorkstation:
// IDS_MEMBER_11209 "Standalone Workstation"
ids = IDS_MEMBER_11209;
fDomain = FALSE;
break;
case DsRole_RoleMemberWorkstation:
// IDS_MEMBER_11210 "Member Workstation"
ids = IDS_MEMBER_11210;
fDomain = TRUE;
break;
case DsRole_RoleStandaloneServer:
// IDS_MEMBER_11211 "Standalone Server"
ids = IDS_MEMBER_11211;
fDomain = FALSE;
break;
case DsRole_RoleMemberServer:
// IDS_MEMBER_11212 "Member Server"
ids = IDS_MEMBER_11212;
fDomain = TRUE;
break;
case DsRole_RoleBackupDomainController:
// IDS_MEMBER_11213 "Backup Domain Controller"
ids = IDS_MEMBER_11213;
fDomain = TRUE;
break;
case DsRole_RolePrimaryDomainController:
// IDS_MEMBER_11214 "Primary Domain Controller"
ids = IDS_MEMBER_11214;
fDomain = TRUE;
break;
default:
if (pParams->fReallyVerbose)
{
// IDS_MEMBER_11215 "<Unknown Role> %ld"
PrintMessage(pParams, IDS_MEMBER_11215,
pPrimaryDomain->MachineRole );
}
ids = 0;
fDomain = TRUE;
break;
}
if (pParams->fReallyVerbose && ids)
PrintMessage(pParams, ids);
if (pParams->fReallyVerbose)
PrintNewLine(pParams, 1);
if ( pPrimaryDomain->DomainNameFlat == NULL )
{
// IDS_MEMBER_11217 " Netbios Domain name is not specified: "
// IDS_MEMBER_11232 " Netbios Workgroup name is not specified: "
ids = fDomain ? IDS_MEMBER_11217 : IDS_MEMBER_11232;
PrintMessage(pParams, ids);
}
else
{
// IDS_MEMBER_11216 " Netbios Domain name: %ws\n"
// IDS_MEMBER_11218 " Netbios Workgroup name: %ws\n"
ids = fDomain ? IDS_MEMBER_11216 : IDS_MEMBER_11218;
if (pParams->fReallyVerbose)
PrintMessage(pParams, ids,
pPrimaryDomain->DomainNameFlat );
}
if ( pPrimaryDomain->DomainNameDns == NULL )
{
// IDS_MEMBER_11219 " Dns domain name is not specified.\n"
PrintMessage(pParams, IDS_MEMBER_11219 );
}
else
{
if (pParams->fReallyVerbose)
// IDS_MEMBER_11220 " Dns domain name: %ws\n"
PrintMessage(pParams, IDS_MEMBER_11220,
pPrimaryDomain->DomainNameDns );
}
if ( pPrimaryDomain->DomainForestName == NULL )
{
// IDS_MEMBER_11221 " Dns forest name is not specified.\n"
PrintMessage(pParams, IDS_MEMBER_11221 );
}
else
{
if (pParams->fReallyVerbose)
// IDS_MEMBER_11222 " Dns forest name: %ws\n"
PrintMessage(pParams, IDS_MEMBER_11222,
pPrimaryDomain->DomainForestName );
}
if ( pParams->fReallyVerbose )
{
WCHAR swzGuid[64];
// IDS_MEMBER_11223 " Domain Guid: "
PrintMessage(pParams, IDS_MEMBER_11223);
StringFromGUID2(&pPrimaryDomain->DomainGuid,
swzGuid,
DimensionOf(swzGuid));
PrintMessage(pParams, IDS_GLOBAL_WSTRING, swzGuid);
PrintNewLine(pParams, 1);
if ( pPrimaryDomain->MachineRole != DsRole_RoleStandaloneWorkstation &&
pPrimaryDomain->MachineRole != DsRole_RoleStandaloneServer )
{
// IDS_MEMBER_11227 " Domain Sid: "
PrintMessage(pParams, IDS_MEMBER_11227);
PrintSid( pParams, pResults->Global.pMemberDomain->DomainSid );
}
// IDS_MEMBER_11228 " Logon User: %wZ\n"
PrintMessage(pParams, IDS_MEMBER_11228, pResults->Global.pLogonUser );
// IDS_MEMBER_11229 " Logon Domain: %wZ\n"
PrintMessage(pParams, IDS_MEMBER_11229, pResults->Global.pLogonDomainName );
}
if ( pParams->fReallyVerbose)
{
if (pResults->Global.pswzLogonServer &&
pResults->Global.pswzLogonServer[0])
// IDS_MEMBER_11230 " Logon Server: %ws\n"
PrintMessage(pParams, IDS_MEMBER_11230, pResults->Global.pswzLogonServer );
if (pResults->Global.fLogonWithCachedCredentials)
{
// IDS_MEMBER_11231 " [WARNING] Member: User was logged on with cached credentials\n"
PrintMessage(pParams, IDS_MEMBER_11231);
}
}
L_ERROR:
return;
}
/*!--------------------------------------------------------------------------
MemberPerInterfacePrint
-
Author: KennT
---------------------------------------------------------------------------*/
void MemberPerInterfacePrint(IN NETDIAG_PARAMS *pParams,
IN NETDIAG_RESULT *pResults,
IN INTERFACE_RESULT *pIfResult)
{
}
/*!--------------------------------------------------------------------------
MemberCleanup
-
Author: KennT
---------------------------------------------------------------------------*/
void MemberCleanup(IN NETDIAG_PARAMS *pParams,
IN OUT NETDIAG_RESULT *pResults)
{
free(pResults->Global.pswzLogonServer);
pResults->Global.pswzLogonServer = NULL;
}