mirror of https://github.com/lianthony/NT4.0
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.
2566 lines
69 KiB
2566 lines
69 KiB
/**********************************************************************/
|
|
/** Microsoft Windows NT **/
|
|
/** Copyright(c) Microsoft Corp., 1991 **/
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Domain.cxx
|
|
|
|
OLDNAME: NCPADOMN.CXX: Windows/NT Network Control Panel Applet
|
|
|
|
Domain membership and computer name handling.
|
|
|
|
FILE HISTORY:
|
|
DavidHov 12/17/91 Created
|
|
DavidHov 9/15/92 Changed fIdw dependencies
|
|
to CODEWORK_BETA1; made
|
|
password changing dependent
|
|
upon CODEWORK_BETA1.
|
|
|
|
NOTES:
|
|
|
|
*/
|
|
|
|
#include "pch.hxx" // Precompiled header
|
|
#pragma hdrstop
|
|
|
|
#define CODEWORK_BETA1 1
|
|
const TCHAR * const pszIPCName = SZ("\\IPC$") ;
|
|
|
|
const INT MAX_DOMAINNAME_LENGTH = 15;
|
|
|
|
|
|
|
|
extern BOOL NetBiosNameInUse( TCHAR * pszName );
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::ValidateName
|
|
|
|
SYNOPSIS: Validate the given name. If failure,
|
|
optionally pop up a MessageBox and
|
|
complain.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES: Should internal spaces be failed?
|
|
|
|
HISTORY: DavidHov 4/14/92 Created
|
|
DavidHov 9/29/92 Added 'fAsPdc'
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER :: ValidateName (
|
|
INT iNameType,
|
|
LPCTSTR pszName,
|
|
BOOL fAsPdc )
|
|
{
|
|
INT midWarn = 0 ;
|
|
|
|
// Validate the name.
|
|
APIERR err = ::I_NetNameValidate( NULL,
|
|
(LPTSTR)pszName,
|
|
iNameType,
|
|
0 ) ;
|
|
|
|
// See if LanManNT and a new domain is being created.
|
|
// In this case, a domain must not exist by the given name.
|
|
if ( err == 0 && iNameType == NAMETYPE_COMPUTER )
|
|
{
|
|
if ( NetBiosNameInUse( (LPTSTR)pszName ) )
|
|
{
|
|
err = IDS_NCPA_COMPUTER_EXISTS;
|
|
}
|
|
}
|
|
else if ( err == 0
|
|
&& iNameType == NAMETYPE_DOMAIN
|
|
&& fAsPdc )
|
|
{
|
|
// new code alert: this should be reviewed
|
|
NLS_STR nlsDomainName;
|
|
|
|
QueryDisplayDomainName( nlsDomainName );
|
|
|
|
// make sure the name has changed before doing any tests
|
|
if (::I_MNetComputerNameCompare( pszName, nlsDomainName ))
|
|
// end new code
|
|
{
|
|
// See if we can contact any DC of the new domain.
|
|
DOMAIN domain(pszName, TRUE ) ;
|
|
|
|
TCHAR szBuiltin[] = TEXT("builtin");
|
|
|
|
if ( lstrcmpi( pszName, szBuiltin ) == 0
|
|
|| domain.GetInfo() == 0 )
|
|
{
|
|
err = midWarn = IDS_NCPA_DOMAIN_EXISTS ;
|
|
}
|
|
|
|
if ( err == 0 )
|
|
{
|
|
// Now make sure there isn't another computer on the net whose
|
|
// computername is the same as the domain name or the computername.
|
|
// We do this using NetWkstUserSetInfo() to set the other domains
|
|
// field temporarily to the name we want to use as the domain name.
|
|
|
|
do { // Error breakout loop
|
|
PWKSTA_USER_INFO_1101 pwui1101Save = NULL;
|
|
APIERR tmperr = ::NetWkstaUserGetInfo( NULL,
|
|
1101,
|
|
(LPBYTE *)&pwui1101Save );
|
|
if ( tmperr == NERR_WkstaNotStarted )
|
|
{
|
|
// Let the user go on
|
|
// CODEWORK, should we popup a warning message here?
|
|
break;
|
|
}
|
|
else if ( tmperr != NERR_Success )
|
|
{
|
|
err = tmperr;
|
|
break;
|
|
}
|
|
|
|
WKSTA_USER_INFO_1101 wui1101;
|
|
wui1101.wkui1101_oth_domains = (LPTSTR)pszName;
|
|
|
|
tmperr = ::NetWkstaUserSetInfo( NULL,
|
|
1101,
|
|
(LPBYTE) &wui1101,
|
|
NULL );
|
|
|
|
if ( tmperr == NERR_Success )
|
|
{
|
|
::NetWkstaUserSetInfo( NULL,
|
|
1101,
|
|
(LPBYTE) pwui1101Save,
|
|
NULL );
|
|
}
|
|
else
|
|
{
|
|
err = midWarn = IDS_NCPA_DOMAIN_EXISTS;
|
|
}
|
|
|
|
::NetApiBufferFree( pwui1101Save );
|
|
|
|
} while ( FALSE ) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( err == 0 )
|
|
{
|
|
midWarn = 0;
|
|
}
|
|
else
|
|
{
|
|
// If the warning message has not been set, default it.
|
|
|
|
if ( midWarn == 0 )
|
|
{
|
|
switch ( iNameType )
|
|
{
|
|
case NAMETYPE_USER:
|
|
midWarn = IDS_DOMMGR_INV_USER_NAME ;
|
|
break ;
|
|
case NAMETYPE_COMPUTER:
|
|
midWarn = (err == IDS_NCPA_COMPUTER_EXISTS) ? err
|
|
: IDS_DOMMGR_INV_COMPUTER_NAME ;
|
|
break ;
|
|
case NAMETYPE_PASSWORD:
|
|
midWarn = IDS_DOMMGR_INV_PASSWORD ;
|
|
break ;
|
|
case NAMETYPE_DOMAIN:
|
|
midWarn = IDS_DOMMGR_INV_DOMAIN_NAME ;
|
|
break ;
|
|
case NAMETYPE_WORKGROUP:
|
|
midWarn = IDS_DOMMGR_INV_WORKGROUP_NAME ;
|
|
break;
|
|
default:
|
|
midWarn = IDS_DOMMGR_INV_NAME ;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
}
|
|
return midWarn ;
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::QueryRole
|
|
|
|
SYNOPSIS: Return the currently indicated computer role.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
EROLE_DC - Primary DC
|
|
EROLE_MEMBER - BDC
|
|
EROLE_TRUSTED - a member of domain/workgroup
|
|
EROLE_STANDALONE - Not a member of anything
|
|
|
|
HISTORY: DavidHov 4/6/92 Created
|
|
|
|
********************************************************************/
|
|
ENUM_DOMAIN_ROLE DOMAIN_MANAGER :: QueryRole ()
|
|
{
|
|
ENUM_DOMAIN_ROLE eRole = EROLE_UNKNOWN ;
|
|
|
|
if ( _fLanmanNt )
|
|
{
|
|
if ( IsPrimaryDC() )
|
|
eRole = EROLE_DC ;
|
|
else
|
|
eRole = EROLE_MEMBER ;
|
|
}
|
|
else if ( _fMember )
|
|
eRole = EROLE_TRUSTED ;
|
|
else
|
|
eRole = EROLE_STANDALONE ;
|
|
|
|
return eRole ;
|
|
}
|
|
|
|
void DOMAIN_MANAGER :: SetInstallRole( ENUM_DOMAIN_ROLE eRole )
|
|
{
|
|
_fInstall = TRUE;
|
|
|
|
switch (eRole)
|
|
{
|
|
case EROLE_DC :
|
|
_fCreateDomain = TRUE;
|
|
// no break
|
|
case EROLE_MEMBER:
|
|
_fLanmanNt = TRUE;
|
|
break;
|
|
|
|
case EROLE_TRUSTED:
|
|
_fMember = TRUE;
|
|
break;
|
|
|
|
case EROLE_STANDALONE:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::QueryMachineAccountFlags
|
|
|
|
SYNOPSIS: Return the NET API account flags for the
|
|
remote machine account.
|
|
|
|
ENTRY: DWORD * pdwFlags place to store flags
|
|
|
|
EXIT: APIERR result of NET API
|
|
|
|
RETURNS: Account flags if successful.
|
|
|
|
CAVEATS: This routine relies on valid settings for _nlsDcName
|
|
|
|
NOTES: The "info level" for this non-Admin API did not
|
|
exist under LM 2.x, so no wrappered access is possible
|
|
using the LMOBJ classes.
|
|
|
|
HISTORY:
|
|
DavidHov 8/15/92 Created
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER :: QueryMachineAccountFlags ( DWORD * pdwFlags )
|
|
{
|
|
APIERR err ;
|
|
NLS_STR nlsMachineAccountName ;
|
|
LPBYTE pUserInfo = NULL ;
|
|
|
|
if ( err = MachineAccountName( & nlsMachineAccountName ) )
|
|
return err ;
|
|
|
|
TRACEEOL( SZ("NCPA/DOMMGR: Get account flags on PDC [")
|
|
<< _nlsDcName.QueryPch()
|
|
<< SZ("] for account [")
|
|
<< nlsMachineAccountName.QueryPch()
|
|
<< SZ("].") ) ;
|
|
|
|
err = ::NetUserGetInfo( (TCHAR *) _nlsDcName.QueryPch(),
|
|
(TCHAR *) nlsMachineAccountName.QueryPch(),
|
|
20,
|
|
& pUserInfo ) ;
|
|
|
|
if ( err == 0 )
|
|
{
|
|
*pdwFlags = ((USER_INFO_20 *) pUserInfo)->usri20_flags ;
|
|
::NetApiBufferFree( pUserInfo ) ;
|
|
}
|
|
|
|
return err ;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::SetMachineAccountFlags
|
|
|
|
SYNOPSIS: Set the NET API account flags for the
|
|
remote machine account.
|
|
|
|
ENTRY: DWORD * pdwFlags place to store flags
|
|
|
|
EXIT: APIERR result of NET API
|
|
|
|
CAVEATS: This routine relies on valid settings for _nlsDcName
|
|
|
|
NOTES: The "info level" for this non-Admin API did not
|
|
exist under LM 2.x, so no wrappered access is possible
|
|
using the LMOBJ classes.
|
|
|
|
HISTORY:
|
|
Thomaspa 11/09/92 Created
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER :: SetMachineAccountFlags ( DWORD dwFlags )
|
|
{
|
|
APIERR err ;
|
|
NLS_STR nlsMachineAccountName ;
|
|
LPBYTE pUserInfo = NULL ;
|
|
|
|
if ( err = MachineAccountName( & nlsMachineAccountName ) )
|
|
return err ;
|
|
|
|
TRACEEOL( SZ("NCPA/DOMMGR: Get account flags on PDC [")
|
|
<< _nlsDcName.QueryPch()
|
|
<< SZ("] for account [")
|
|
<< nlsMachineAccountName.QueryPch()
|
|
<< SZ("].") ) ;
|
|
|
|
err = ::NetUserGetInfo( (TCHAR *) _nlsDcName.QueryPch(),
|
|
(TCHAR *) nlsMachineAccountName.QueryPch(),
|
|
20,
|
|
& pUserInfo ) ;
|
|
TRACEEOL( SZ("NCPA/DOMMGR: Get account flags on PDC returned ")
|
|
<< err );
|
|
|
|
if ( err == 0 )
|
|
{
|
|
((USER_INFO_20 *)pUserInfo)->usri20_flags = dwFlags;
|
|
|
|
TRACEEOL( SZ("NCPA/DOMMGR: Set account flags on PDC [")
|
|
<< _nlsDcName.QueryPch()
|
|
<< SZ("] for account [")
|
|
<< nlsMachineAccountName.QueryPch()
|
|
<< SZ("].")
|
|
<< SZ("Flags = ")
|
|
<< dwFlags ) ;
|
|
|
|
err = ::NetUserSetInfo( (TCHAR *) _nlsDcName.QueryPch(),
|
|
(TCHAR *) nlsMachineAccountName.QueryPch(),
|
|
20,
|
|
pUserInfo,
|
|
NULL );
|
|
|
|
TRACEEOL( SZ("NCPA/DOMMGR: Set account flags on PDC returned ")
|
|
<< err );
|
|
::NetApiBufferFree( pUserInfo ) ;
|
|
}
|
|
|
|
return err ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::GetDCName
|
|
|
|
SYNOPSIS: Get the DC name; set 'fDomainExists' accordingly
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
DavidHov 4/6/92 Created
|
|
DavidHov 8/31/92 Changed to verify domain is WinNT
|
|
Davidhov 9/17/92 Changed to allow use of BDC if
|
|
we're verifying an existing server
|
|
account.
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER :: GetDCName ()
|
|
{
|
|
APIERR err = 0 ;
|
|
|
|
TRACEEOL( SZ("NCPA/DOMMGR: get DC name for ")
|
|
<< _nlsDomainName.QueryPch() ) ;
|
|
|
|
// Construct a DOMAIN object. Allow use of a BDC if we're just
|
|
// verifying an existing server account.
|
|
|
|
DOMAIN domain( _nlsDomainName.QueryPch(), _fUseComputerPassword ) ;
|
|
|
|
_fDomainExists = FALSE ;
|
|
|
|
do
|
|
{
|
|
if ( err = domain.GetInfo() )
|
|
break ;
|
|
|
|
_nlsDcName = domain.QueryPDC() ;
|
|
|
|
if ( err = _nlsDcName.QueryError() )
|
|
break ;
|
|
|
|
_fDomainExists = TRUE ;
|
|
}
|
|
while ( FALSE ) ;
|
|
|
|
#if defined(DEBUG)
|
|
if ( err == 0 )
|
|
{
|
|
TRACEEOL( SZ("NCPA/DOMMGR: DC name is ") << _nlsDcName.QueryPch() ) ;
|
|
}
|
|
else
|
|
{
|
|
TRACEEOL( SZ("NCPA/DOMMGR: DC name query FAILED, err ") << err ) ;
|
|
}
|
|
#endif
|
|
|
|
return err ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::MachineAccountName
|
|
|
|
SYNOPSIS: Generate the name of the domain's machine account
|
|
for this computer.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
DavidHov 7/28/92 Created
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER :: MachineAccountName ( NLS_STR * pnlsMachineAccount )
|
|
{
|
|
NLS_STR nlsPostfix ;
|
|
APIERR err ;
|
|
|
|
// Create the name for the machine account
|
|
|
|
do
|
|
{
|
|
if ( err = nlsPostfix.QueryError() )
|
|
break ;
|
|
|
|
if ( err = QueryPendingComputerName( pnlsMachineAccount ) )
|
|
break;
|
|
|
|
if ( err = nlsPostfix.MapCopyFrom( (WCHAR *) SSI_ACCOUNT_NAME_POSTFIX ) )
|
|
break ;
|
|
|
|
if ( err = pnlsMachineAccount->Append( nlsPostfix ) )
|
|
break ;
|
|
}
|
|
while ( FALSE ) ;
|
|
|
|
return err ;
|
|
}
|
|
|
|
|
|
|
|
|
|
// Delete any existing use of the DC's IPC$ share.
|
|
|
|
static APIERR disconnectIPC ( const NLS_STR * pnlsDcName )
|
|
{
|
|
NLS_STR nlsIPC ;
|
|
APIERR err = 0 ;
|
|
|
|
do
|
|
{
|
|
// Construct the UNC share name;
|
|
// the DC name is in UNC form.
|
|
|
|
nlsIPC = *pnlsDcName ;
|
|
nlsIPC.Append( pszIPCName ) ;
|
|
|
|
if ( err = nlsIPC.QueryError() )
|
|
break ;
|
|
|
|
err = ::NetUseDel( NULL,
|
|
(TCHAR *) nlsIPC.QueryPch(),
|
|
USE_LOTS_OF_FORCE ) ;
|
|
|
|
}
|
|
while ( FALSE ) ;
|
|
|
|
TRACEEOL( SZ("NCPA/DOMMGR: NetUseDel() on [")
|
|
<< nlsIPC.QueryPch()
|
|
<< SZ("] returned ")
|
|
<< err );
|
|
return err ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::UseIPConDC
|
|
|
|
SYNOPSIS: Attempt to "net use" IPC$ the Domain Controller
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES: This function attempts to connect to the IPC$
|
|
device on the DC, using the name/password combination
|
|
specified by the user in the Domain Settings dialog.
|
|
|
|
This function may fail if the user account used to establish
|
|
the session is a Server or Workstation account. In this
|
|
case, a NULL session will be established and the error
|
|
will be returned.
|
|
|
|
HISTORY:
|
|
DavidHov 4/6/92 Created
|
|
Thomaspa 11/9/92 Handle machine account errors.
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER :: UseIPConDC ()
|
|
{
|
|
APIERR err = 0 ;
|
|
NLS_STR nlsIPC,
|
|
nlsAccount ;
|
|
const NLS_STR * pnlsPw ;
|
|
const NLS_STR * pnlsName ;
|
|
const TCHAR * pszPw = NULL ;
|
|
const TCHAR * pszName = NULL ;
|
|
const TCHAR * pszDomain = NULL ;
|
|
|
|
DEVICE2 devIPC( SZ("") ) ; // Deviceless connection
|
|
|
|
do // PSEUDO-LOOP
|
|
{
|
|
if ( err = devIPC.GetInfo() )
|
|
{
|
|
// The DEVICE2 is bogus; fail entirely...
|
|
|
|
TRACEEOL( SZ("NCPA/DOMMGR: use IPC$: DEVICE2 failure") );
|
|
|
|
break ;
|
|
}
|
|
|
|
// Construct the UNC share name;
|
|
// the DC name is in UNC form.
|
|
|
|
nlsIPC = _nlsDcName ;
|
|
nlsIPC.Append( pszIPCName ) ;
|
|
|
|
if ( err = nlsIPC.QueryError() )
|
|
break ;
|
|
|
|
// If the user entered the Computer Account Password,
|
|
// connect using the Domain Machine Account name and
|
|
// the password entered. Otherwise, it's an admin account,
|
|
// so use the account name and password given.
|
|
|
|
if ( _fUseComputerPassword )
|
|
{
|
|
if ( err = MachineAccountName( & nlsAccount ) )
|
|
break ;
|
|
pnlsName = & nlsAccount ;
|
|
pnlsPw = & _nlsComputerAcctPassword ;
|
|
}
|
|
else
|
|
{
|
|
pnlsName = & _nlsLogonUserName ;
|
|
pnlsPw = & _nlsLogonPassword ;
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( pnlsPw->QueryTextLength() > 0 )
|
|
pszPw = pnlsPw->QueryPch() ;
|
|
|
|
if ( pszPw == NULL )
|
|
pszPw = SZ("");
|
|
|
|
if ( pnlsName->QueryTextLength() > 0 )
|
|
pszName = pnlsName->QueryPch() ;
|
|
|
|
if ( !_fUseComputerPassword && _nlsLogonDomain.QueryTextLength() > 0 )
|
|
{
|
|
pszDomain = _nlsLogonDomain.QueryPch();
|
|
}
|
|
else
|
|
{
|
|
pszDomain = _nlsDomainName.QueryPch();
|
|
}
|
|
|
|
TRACEEOL( SZ("NCPA/DOMMGR: use [")
|
|
<< nlsIPC.QueryPch()
|
|
<< SZ("] username [")
|
|
<< pnlsName->QueryPch()
|
|
<< SZ("] password [")
|
|
<< pnlsPw->QueryPch()
|
|
<< SZ("] domain [")
|
|
<< pszDomain
|
|
<< SZ("].") ) ;
|
|
|
|
// Attempt to use IPC$...
|
|
|
|
// Use a NULL domain name if using an administrator name and password
|
|
// so that a name from a trusted domain can be entered.
|
|
err = devIPC.Connect( nlsIPC.QueryPch(),
|
|
pszPw,
|
|
pszName,
|
|
pszDomain ) ;
|
|
|
|
if ( _fUseComputerPassword && (err == ERROR_LOGON_FAILURE) )
|
|
{
|
|
// Just in case you are just "rejoining" a renamed domain.
|
|
|
|
NLS_STR nlsSecretName;
|
|
|
|
APIERR err2 = nlsSecretName.MapCopyFrom(
|
|
(WCHAR *)SSI_SECRET_NAME ) ;
|
|
|
|
if ( err2 == NERR_Success )
|
|
{
|
|
LSA_SECRET lsaSecretName( nlsSecretName );
|
|
NLS_STR nlsSecretPassword;
|
|
NLS_STR nlsOldPassword;
|
|
if ( lsaSecretName.QueryError() == NERR_Success
|
|
&& lsaSecretName.Open( *this, SECRET_ALL_ACCESS )
|
|
== NERR_Success
|
|
&& nlsSecretPassword.QueryError() == NERR_Success
|
|
&& nlsOldPassword.QueryError() == NERR_Success
|
|
&& lsaSecretName.QueryInfo( &nlsSecretPassword,
|
|
&nlsOldPassword,
|
|
NULL,
|
|
NULL ) == NERR_Success )
|
|
{
|
|
|
|
if ( (err = devIPC.Connect( nlsIPC.QueryPch(),
|
|
nlsSecretPassword.QueryPch(),
|
|
pszName,
|
|
_nlsDomainName.QueryPch()))
|
|
== ERROR_LOGON_FAILURE )
|
|
{
|
|
// Last try, use the old password
|
|
err = devIPC.Connect( nlsIPC.QueryPch(),
|
|
nlsOldPassword.QueryPch(),
|
|
pszName,
|
|
_nlsDomainName.QueryPch() );
|
|
}
|
|
memset ( (void *)nlsSecretPassword.QueryPch(),
|
|
' ',
|
|
nlsSecretPassword.strlen() );
|
|
memset ( (void *)nlsOldPassword.QueryPch(),
|
|
' ',
|
|
nlsOldPassword.strlen() );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( _fUseComputerPassword
|
|
&& ( err == ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT
|
|
|| err == ERROR_NOLOGON_SERVER_TRUST_ACCOUNT ) )
|
|
{
|
|
// Retry using NULL session
|
|
APIERR err2 = devIPC.Connect( nlsIPC.QueryPch(),
|
|
SZ(""),
|
|
SZ(""),
|
|
SZ("") ) ;
|
|
|
|
if ( err2 && err2 != ERROR_SESSION_CREDENTIAL_CONFLICT )
|
|
err = err2 ;
|
|
}
|
|
if ( err )
|
|
break ;
|
|
|
|
// Construct a LOCATION object to verify that
|
|
// the domain is indeed Windows NT.
|
|
{
|
|
BOOL fIsNT ;
|
|
LOCATION locPdc( _nlsDcName, FALSE ) ;
|
|
do
|
|
{
|
|
if ( err = locPdc.QueryError() )
|
|
break ;
|
|
if ( err = locPdc.CheckIfNT( & fIsNT ) )
|
|
break ;
|
|
if ( ! fIsNT )
|
|
err = IDS_NCPA_DOMAIN_NOT_NT ;
|
|
}
|
|
while ( FALSE ) ;
|
|
}
|
|
if ( err )
|
|
{
|
|
disconnectIPC( & _nlsDcName ) ;
|
|
_fDomainExists = FALSE ;
|
|
break ;
|
|
}
|
|
}
|
|
while ( FALSE ) ;
|
|
|
|
#if defined(DEBUG)
|
|
if ( err == 0 )
|
|
{
|
|
TRACEEOL( SZ("NCPA/DOMMGR: use IPC$ on DC successful.") ) ;
|
|
}
|
|
else
|
|
{
|
|
TRACEEOL( SZ("NCPA/DOMMGR: use IPC$ on DC failed; error ")
|
|
<< err ) ;
|
|
}
|
|
#endif
|
|
|
|
return err ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::ChangeMachineAcctPassword
|
|
|
|
SYNOPSIS: Change the password on the remote machine account
|
|
using the current password.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES: Alters the password in one of two ways: either using
|
|
the old password or using the privilege granted by
|
|
the admin account used to establish the use of IPC$.
|
|
|
|
HISTORY:
|
|
DavidHov 8/6/92 Created
|
|
DavidHov 9/3/92 Enhanced to use alternate form of
|
|
SAM_USER::SetPassword() if admin account
|
|
is being used.
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER :: ChangeMachineAcctPassword ()
|
|
{
|
|
NLS_STR nlsAccount,
|
|
nlsMachinePassword ;
|
|
APIERR err ;
|
|
ADMIN_AUTHORITY * pAdminAuth = NULL ;
|
|
SAM_USER * pSamUser = NULL ;
|
|
SAM_RID_MEM samrm ;
|
|
SAM_SID_NAME_USE_MEM samsnum ;
|
|
const TCHAR * pszAccountName ;
|
|
SAM_DOMAIN * pSamDomain ;
|
|
|
|
do
|
|
{
|
|
// Generate the new random password
|
|
|
|
if ( err = nlsMachinePassword.QueryError() )
|
|
break ;
|
|
|
|
if ( err = MachineAccountPassword( & nlsMachinePassword ) )
|
|
break ;
|
|
|
|
// Generate the name of this machine's remote SAM
|
|
// domain machine account
|
|
|
|
if ( err = nlsAccount.QueryError() )
|
|
break ;
|
|
|
|
if ( err = MachineAccountName( & nlsAccount ) )
|
|
break ;
|
|
|
|
pszAccountName = nlsAccount.QueryPch() ;
|
|
|
|
// Construct the authorities necessary to perform this
|
|
// operation.
|
|
|
|
pAdminAuth = new ADMIN_AUTHORITY( _nlsDcName,
|
|
MAXIMUM_ALLOWED,
|
|
MAXIMUM_ALLOWED,
|
|
MAXIMUM_ALLOWED,
|
|
MAXIMUM_ALLOWED ) ;
|
|
if ( pAdminAuth == NULL )
|
|
{
|
|
err = ERROR_NOT_ENOUGH_MEMORY ;
|
|
break ;
|
|
}
|
|
|
|
if ( err = pAdminAuth->QueryError() )
|
|
break ;
|
|
|
|
// Translate the machine account name to a RID.
|
|
|
|
pSamDomain = pAdminAuth->QueryAccountDomain() ;
|
|
|
|
err = pSamDomain->TranslateNamesToRids( & pszAccountName,
|
|
1,
|
|
& samrm,
|
|
& samsnum );
|
|
if ( err )
|
|
break ;
|
|
|
|
TRACEEOL( SZ("NCPA/DOMMGR: Machine acct RID = ")
|
|
<< samrm.QueryRID(0) ) ;
|
|
|
|
// Create a SAM_USER for the machine account
|
|
|
|
pSamUser = new SAM_USER( *pSamDomain,
|
|
samrm.QueryRID(0),
|
|
MAXIMUM_ALLOWED );
|
|
if ( pSamUser == NULL )
|
|
{
|
|
err = ERROR_NOT_ENOUGH_MEMORY ;
|
|
break ;
|
|
}
|
|
if ( err = pSamUser->QueryError() )
|
|
break ;
|
|
|
|
err = pSamUser->SetPassword( nlsMachinePassword ) ;
|
|
|
|
TRACEEOL( SZ("NCPA/DOMMGR: Machine acct p/w set returned: ")
|
|
<< err );
|
|
|
|
if ( err )
|
|
break ;
|
|
|
|
_nlsComputerAcctPassword.CopyFrom( nlsMachinePassword ) ;
|
|
}
|
|
while ( FALSE );
|
|
|
|
delete pSamUser ;
|
|
delete pAdminAuth ;
|
|
|
|
return err ;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::HandleDomainAccount
|
|
|
|
SYNOPSIS: Attempt to create computer account on domain
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES: Behavior is as follows:
|
|
|
|
Generate random new password.
|
|
|
|
Attempt NetUserAdd() on machine account, as is.
|
|
If OK, exit without error.
|
|
|
|
Do NetUserGetInfo() on machine account.
|
|
If fails with "access denied", go to PasswordSet.
|
|
If fails, exit with error.
|
|
|
|
(We now know the account exists.)
|
|
|
|
Attempt NetUserSetInfo() to change
|
|
password.
|
|
If OK, exit without error.
|
|
|
|
Return resulting error.
|
|
|
|
HISTORY:
|
|
DavidHov 4/6/92 Created
|
|
DavidHov 7/28/92 Change to handle machine acct p/w case
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER :: HandleDomainAccount ()
|
|
{
|
|
APIERR err = 0 ;
|
|
NLS_STR nlsAcct,
|
|
nlsPw ;
|
|
DWORD dwAcctFlags ;
|
|
USER_3 * pu3Acct = NULL ;
|
|
UINT uAcctFlags = _fLanmanNt
|
|
? UF_SERVER_TRUST_ACCOUNT
|
|
: UF_WORKSTATION_TRUST_ACCOUNT ;
|
|
|
|
do // Pseudo-loop
|
|
{
|
|
// Generate the machine account name and a password. If
|
|
// non-IDW (retail), generate a random password; otherwise,
|
|
// use the computer name as a password.
|
|
|
|
if ( err = nlsAcct.QueryError() )
|
|
break ;
|
|
|
|
if ( err = nlsPw.QueryError() )
|
|
break ;
|
|
|
|
if ( err = MachineAccountName( & nlsAcct ) )
|
|
break ;
|
|
|
|
if ( err = MachineAccountPassword( & nlsPw ) )
|
|
break ;
|
|
|
|
// If trying an admin account, attempt to create a
|
|
// new machine account. If not, just skip and try to
|
|
// access an existing account. In either case, attempt
|
|
// to change or set the machine account's password to
|
|
// a pseudo-random value if non-IDW.
|
|
|
|
if ( ! _fUseComputerPassword ) // Attempt to create new account
|
|
{
|
|
// Construct the LM_OBJ helping wrapper object for a server account.
|
|
|
|
pu3Acct = new USER_3( nlsAcct.QueryPch(), _nlsDomainName.QueryPch() ) ;
|
|
if ( pu3Acct == NULL )
|
|
{
|
|
err = ERROR_NOT_ENOUGH_MEMORY ;
|
|
break ;
|
|
}
|
|
|
|
// Complete the creation of the USER_3 object.
|
|
if ( err = pu3Acct->QueryError() )
|
|
break ;
|
|
if ( err = pu3Acct->CreateNew() )
|
|
break ;
|
|
if ( err = pu3Acct->SetName( nlsAcct ) )
|
|
break ;
|
|
if ( err = pu3Acct->SetPassword( nlsPw ) )
|
|
break ;
|
|
if ( err = pu3Acct->SetAccountType( (ACCOUNT_TYPE) uAcctFlags ) )
|
|
break ;
|
|
|
|
TRACEEOL( SZ("NCPA/DOMMGR: attempting NetUserAdd(); user: [")
|
|
<< nlsAcct.QueryPch()
|
|
<< SZ("] password: [")
|
|
<< nlsPw.QueryPch()
|
|
<< SZ("] flags: ")
|
|
<< uAcctFlags ) ;
|
|
|
|
// Attempt to add the account for this machine on the DC
|
|
err = pu3Acct->WriteNew() ;
|
|
|
|
if ( err == 0 )
|
|
{
|
|
// SUCCESSFUL! We're done!
|
|
|
|
TRACEEOL( SZ("NCPA/DOMMGR: NetUserAdd() succeeded!") );
|
|
|
|
_nlsComputerAcctPassword.CopyFrom( nlsPw ) ;
|
|
break ;
|
|
}
|
|
|
|
TRACEEOL( SZ("NCPA/DOMMGR: NetUserAdd() failed, error ")
|
|
<< err ) ;
|
|
|
|
// Try to get the flags from an existing account
|
|
|
|
if ( err = QueryMachineAccountFlags( & dwAcctFlags ) )
|
|
{
|
|
TRACEEOL(SZ("NCPA/DOMMGR: Query account flags returned error: ")
|
|
<< err ) ;
|
|
err = IDS_NCPA_MACHINE_ACCT_NOT_FOUND ;
|
|
break ;
|
|
}
|
|
|
|
// Check that the account flags on the remote account are
|
|
// proper for this installation. BDCs are SERVER_TRUST;
|
|
// workstations are WORKSTATION_TRUST.
|
|
|
|
if ( (dwAcctFlags & (_fLanmanNt
|
|
? UF_SERVER_TRUST_ACCOUNT
|
|
: UF_WORKSTATION_TRUST_ACCOUNT)) == 0 )
|
|
{
|
|
TRACEEOL( SZ("NCPA/DOMMGR: Machine acct flags INVALID: ")
|
|
<< dwAcctFlags );
|
|
|
|
err = _fLanmanNt ? IDS_NCPA_MACHINE_ACCT_INVALID_S :
|
|
IDS_NCPA_MACHINE_ACCT_INVALID_W ;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
// The remote account exists. Attempt to change the password.
|
|
|
|
TRACEEOL( SZ("NCPA/DOMMGR: about to change password") );
|
|
|
|
if ( ! _fUseComputerPassword )
|
|
{
|
|
err = ChangeMachineAcctPassword() ;
|
|
TRACEEOL( SZ("NCPA/DOMMGR: change machine acct password returned: ")
|
|
<< err ) ;
|
|
}
|
|
|
|
}
|
|
while ( FALSE ) ;
|
|
|
|
if ( pu3Acct )
|
|
delete pu3Acct ;
|
|
|
|
return err ;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::MachineAccountPassword
|
|
|
|
SYNOPSIS: Generate the initial password of the domain's machine account
|
|
for this computer.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
Thomaspa 11/9/92 Created
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER :: MachineAccountPassword( NLS_STR * pnlsMachinePassword )
|
|
{
|
|
const INT cchMax = LM20_PWLEN < LM20_CNLEN
|
|
? LM20_CNLEN
|
|
: LM20_PWLEN ;
|
|
|
|
TCHAR szPw [cchMax+1] ;
|
|
NLS_STR nlsTemp;
|
|
|
|
|
|
APIERR err ;
|
|
|
|
if ( err = QueryPendingComputerName( &nlsTemp ) )
|
|
return err ;
|
|
|
|
if ( (err = nlsTemp.MapCopyTo( szPw, sizeof( szPw ))) == 0 )
|
|
{
|
|
szPw[LM20_PWLEN] = TCH('\0');
|
|
::CharLowerBuff( szPw, ::strlenf( szPw ) ) ;
|
|
}
|
|
else
|
|
{
|
|
return err ;
|
|
}
|
|
TRACEEOL( SZ("NCPA/DOMMGR: password forced to: ") << szPw ) ;
|
|
|
|
return pnlsMachinePassword->CopyFrom( szPw ) ;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------
|
|
|
|
APIERR DOMAIN_MANAGER::QueryDisplayDomainName( NLS_STR &nlsDomain )
|
|
{
|
|
NLS_STR nlsTempComputerName;
|
|
APIERR err;
|
|
|
|
nlsDomain = _nlsDomainName;
|
|
|
|
if ( err = QueryPendingComputerName( &nlsTempComputerName ) )
|
|
return err;
|
|
|
|
// If the domain name is empty, or it is invalid, or it's the same as the
|
|
// computer name, set the Domain name to "DOMAIN".
|
|
|
|
if ( _nlsDomainName.QueryTextLength() == 0 ||
|
|
::I_NetNameValidate( NULL,
|
|
(TCHAR *) _nlsDomainName.QueryPch(),
|
|
NAMETYPE_DOMAIN,
|
|
0 ) ||
|
|
!::I_MNetComputerNameCompare( _nlsDomainName, nlsTempComputerName ) )
|
|
{
|
|
WCHAR pszTemp[ MAX_DOMAINNAME_LENGTH + 1 ];
|
|
|
|
_err = LoadString( g_hinst, IDS_NCPA_DEFAULT_DOMAIN, pszTemp, MAX_DOMAINNAME_LENGTH );
|
|
|
|
if (0 != _err)
|
|
{
|
|
nlsDomain = pszTemp;
|
|
_nlsDomainName = nlsDomain;
|
|
}
|
|
}
|
|
return( _err );
|
|
}
|
|
|
|
APIERR DOMAIN_MANAGER::QueryDisplayWorkgroupName( NLS_STR &nlsWorkgroup )
|
|
{
|
|
nlsWorkgroup = _nlsWorkgroup;
|
|
return( _err );
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::DOMAIN_MANAGER
|
|
|
|
SYNOPSIS: Functional encapsulation of domain role management
|
|
code.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
DavidHov 4/6/92 Created
|
|
|
|
********************************************************************/
|
|
DOMAIN_MANAGER :: DOMAIN_MANAGER (
|
|
HWND hwOwner, // For birthing dialogs
|
|
ACCESS_MASK accessDesired, // Access to LSA
|
|
REGISTRY_MANAGER * pRegMgr, // To manipulate the Registry
|
|
const TCHAR * pszComputerName, // Focussed computer
|
|
BOOL fInstall ) // TRUE if installation
|
|
: LSA_POLICY( pszComputerName, accessDesired ),
|
|
_err( 0 ),
|
|
_errMsg( 0 ),
|
|
_pRegMgr( pRegMgr ),
|
|
_hwOwner( hwOwner ),
|
|
_pchCmdLine( NULL ),
|
|
_fRegMgrOwned( FALSE ),
|
|
_fAdmin( FALSE ),
|
|
_fDomainExists( FALSE ),
|
|
_fCreateDomain( FALSE ),
|
|
_fMember( FALSE ),
|
|
_fInstall( fInstall ),
|
|
_fIdw( FALSE ),
|
|
_fLanmanNt( FALSE ),
|
|
_fExpress( FALSE ),
|
|
_fUseComputerPassword( TRUE ),
|
|
_fComputerNameChanged( FALSE ),
|
|
_fDomainChanged( FALSE ),
|
|
_fDlgDomainState( FALSE ),
|
|
_fAutoInstall( FALSE ),
|
|
_enumRole( EROLE_UNKNOWN ),
|
|
_pscManager( NULL )
|
|
{
|
|
APIERR err = 0 ;
|
|
if ( QueryError() )
|
|
return ;
|
|
|
|
if ( _pRegMgr == NULL )
|
|
{
|
|
_fRegMgrOwned = TRUE ;
|
|
|
|
_pRegMgr = new REGISTRY_MANAGER ;
|
|
|
|
if ( _pRegMgr == NULL )
|
|
{
|
|
err = ERROR_NOT_ENOUGH_MEMORY ;
|
|
}
|
|
else
|
|
err = _pRegMgr->QueryError() ;
|
|
}
|
|
|
|
if ( err == 0 )
|
|
{
|
|
// CODEWORK: If we're installing, the Bowser and
|
|
// Rdr drivers get upset if there's not a
|
|
// primary domain name, so supply one if necessary.
|
|
|
|
if ( _fInstall
|
|
&& ( QueryPrimaryBrowserGroup( & _nlsWorkgroup ) != 0
|
|
|| _nlsWorkgroup.QueryTextLength() == 0 ) )
|
|
{
|
|
if ( SetDefaultWorkgroupName() == 0 )
|
|
{
|
|
err = SetWorkgroupName( _nlsWorkgroup ) ;
|
|
}
|
|
}
|
|
|
|
err = QueryCurrentInfo() ;
|
|
}
|
|
|
|
|
|
if ( err )
|
|
{
|
|
TRACEEOL( SZ("NCPA/DOMMGR: ct failed, error ") << err );
|
|
ReportError( err ) ;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::~DOMAIN_MANAGER
|
|
|
|
SYNOPSIS:
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
DavidHov 4/6/92 Created
|
|
|
|
********************************************************************/
|
|
DOMAIN_MANAGER :: ~ DOMAIN_MANAGER ()
|
|
{
|
|
if ( _fRegMgrOwned )
|
|
delete _pRegMgr ;
|
|
_pRegMgr = NULL ;
|
|
|
|
// Now clear out any passwords
|
|
memset ( (void *)_nlsLogonPassword.QueryPch(),
|
|
' ',
|
|
_nlsLogonPassword.strlen() );
|
|
|
|
memset ( (void *)_nlsComputerAcctPassword.QueryPch(),
|
|
' ',
|
|
_nlsComputerAcctPassword.strlen() );
|
|
memset ( (void *)_nlsComputerAcctOldPw.QueryPch(),
|
|
' ',
|
|
_nlsComputerAcctOldPw.strlen() );
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::AdjustDomain
|
|
|
|
SYNOPSIS: Performs SAM account handling to either add or
|
|
remove the Domain Admins group from the local
|
|
admins alias.
|
|
|
|
ENTRY: BOOL fAfterJoining TRUE if we just joined
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY: DavidHov 10/16/92 Add/remove domain users group
|
|
to/from local users alias
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER :: AdjustDomain ( BOOL fAfterJoining )
|
|
{
|
|
APIERR err = 0 ;
|
|
|
|
ASSERT( ! _fInstall ) ; // This should only happen post hoc
|
|
|
|
LSA_PRIMARY_DOM_INFO_MEM lspdim ;
|
|
PSID psid = NULL ;
|
|
|
|
// Things requiring cleanup
|
|
|
|
ADMIN_AUTHORITY * pAdminAuth = NULL ;
|
|
SAM_ALIAS * pSamAlias = NULL ;
|
|
OS_SID * pOsSid = NULL ;
|
|
|
|
#define RID_ALIAS_PAIRS 2
|
|
|
|
static ULONG ridAliasPairs [RID_ALIAS_PAIRS][2] =
|
|
{
|
|
// Add this group RID .... to this alias
|
|
|
|
{ DOMAIN_GROUP_RID_ADMINS, DOMAIN_ALIAS_RID_ADMINS },
|
|
{ DOMAIN_GROUP_RID_USERS, DOMAIN_ALIAS_RID_USERS }
|
|
};
|
|
|
|
do
|
|
{
|
|
TRACEEOL( "NCPA/DOMN: AdjustDomain: ." ) ;
|
|
|
|
// Validate the domain info and get the new domain's SID
|
|
|
|
if ( err = lspdim.QueryError() )
|
|
break ;
|
|
|
|
if ( err = GetPrimaryDomain( & lspdim ) )
|
|
break ;
|
|
|
|
if ( (psid = lspdim.QueryPSID()) == NULL )
|
|
{
|
|
ASSERT( "Domain SID is NULL after joining domain." );
|
|
break ;
|
|
}
|
|
|
|
// Construct the ADMIN_AUTHORITY for this computer
|
|
|
|
pAdminAuth = new ADMIN_AUTHORITY( NULL,
|
|
MAXIMUM_ALLOWED,
|
|
MAXIMUM_ALLOWED,
|
|
MAXIMUM_ALLOWED,
|
|
MAXIMUM_ALLOWED ) ;
|
|
if ( pAdminAuth == NULL )
|
|
{
|
|
err = ERROR_NOT_ENOUGH_MEMORY ;
|
|
break ;
|
|
}
|
|
|
|
TRACEEOL( "NCPA/DOMN: AdjustDomain: .." ) ;
|
|
|
|
if ( err = pAdminAuth->QueryError() )
|
|
{
|
|
TRACEEOL( SZ("NCPA/DOMN: ADMIN_AUTHORITY failed: ") << err ) ;
|
|
break ;
|
|
}
|
|
|
|
for ( INT cRid = 0 ; cRid < RID_ALIAS_PAIRS ; cRid ++ )
|
|
{
|
|
// Build the OS_SID representing the Domain group
|
|
|
|
TRACEEOL( "NCPA/DOMN: AdjustDomain: ..." ) ;
|
|
|
|
pOsSid = new OS_SID( psid, ridAliasPairs[cRid][0] ) ;
|
|
if ( pOsSid == NULL )
|
|
{
|
|
err = ERROR_NOT_ENOUGH_MEMORY ;
|
|
break ;
|
|
}
|
|
if ( err = pOsSid->QueryError() )
|
|
break ;
|
|
|
|
#if defined(DEBUG)
|
|
{
|
|
NLS_STR nlsSidId ;
|
|
APIERR err ;
|
|
if ( err = pOsSid->QueryRawID( & nlsSidId ) )
|
|
{
|
|
TRACEEOL( SZ("NCPA/DOMN: cant get raw id for domain group; error ")
|
|
<< err ) ;
|
|
}
|
|
else
|
|
{
|
|
TRACEEOL( SZ("NCPA/DOMN: id for domain group: ")
|
|
<< nlsSidId.QueryPch() ) ;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Get a SAM_ALIAS to the local alias
|
|
|
|
TRACEEOL( "NCPA/DOMN: AdjustDomain: ...." ) ;
|
|
|
|
pSamAlias = new SAM_ALIAS( *pAdminAuth->QueryBuiltinDomain(),
|
|
ridAliasPairs[cRid][1] );
|
|
if ( pSamAlias == NULL )
|
|
{
|
|
err = ERROR_NOT_ENOUGH_MEMORY ;
|
|
break ;
|
|
}
|
|
if ( err = pSamAlias->QueryError() )
|
|
break ;
|
|
|
|
// Add or remove the new domain's group
|
|
// Group to/from the local alias.
|
|
// If simple error, ignore it.
|
|
|
|
TRACEEOL( "NCPA/DOMN: AdjustDomain: ....." ) ;
|
|
|
|
if ( fAfterJoining )
|
|
{
|
|
err = pSamAlias->AddMember( pOsSid->QueryPSID() ) ;
|
|
if ( err == ERROR_MEMBER_IN_ALIAS )
|
|
err = 0 ;
|
|
}
|
|
else
|
|
{
|
|
err = pSamAlias->RemoveMember( pOsSid->QueryPSID() ) ;
|
|
if ( err == ERROR_MEMBER_NOT_IN_ALIAS )
|
|
err = 0 ;
|
|
}
|
|
|
|
TRACEEOL( "NCPA/DOMN: AdjustDomain: ......" ) ;
|
|
|
|
if ( err )
|
|
break ;
|
|
|
|
delete pOsSid ;
|
|
pOsSid = NULL ;
|
|
delete pSamAlias ;
|
|
pSamAlias = NULL ;
|
|
}
|
|
}
|
|
while ( FALSE );
|
|
|
|
delete pOsSid ;
|
|
delete pSamAlias ;
|
|
delete pAdminAuth ;
|
|
|
|
return err ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::RenameDomain
|
|
|
|
SYNOPSIS: Changes the domain name, but keeps the same SID.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES: Handles the local (LSA) side of domain creation
|
|
or joining.
|
|
|
|
This function does NOT change the
|
|
state of the primary object instance variables
|
|
such as "_fMember".
|
|
|
|
HISTORY: Thomaspa 4/5/93
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER :: RenameDomain ()
|
|
{
|
|
APIERR err = NERR_Success;
|
|
// First change the Primary domain name
|
|
do { // Error breakout loop
|
|
LSA_PRIMARY_DOM_INFO_MEM lpdimSave;
|
|
if ( err = lpdimSave.QueryError() )
|
|
{
|
|
break;
|
|
}
|
|
if ( err = SetPrimaryDomainName( &_nlsDomainName ) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
// if this is a DC, change the Accounts domain name
|
|
if ( _fLanmanNt )
|
|
{
|
|
if ( err = SetAccountDomainName( &_nlsDomainName ) )
|
|
{
|
|
// Better try to restore the original name
|
|
NLS_STR nlsRestore;
|
|
lpdimSave.QueryName( &nlsRestore );
|
|
SetPrimaryDomainName( &nlsRestore );
|
|
break;
|
|
}
|
|
}
|
|
} while ( FALSE );
|
|
|
|
if ( err == NERR_Success )
|
|
_fDomainChanged = TRUE ;
|
|
|
|
return err;
|
|
}
|
|
|
|
static const int maxMultiStrValueSize = 4000 ;
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::CacheTrustedDomains
|
|
|
|
SYNOPSIS: Seeds the netlogon service's cache of trusted
|
|
domains.
|
|
|
|
ENTRY: none
|
|
|
|
EXIT: none
|
|
|
|
RETURNS: NERR_Success on success, otherwise an APIERR
|
|
|
|
NOTES: Assumes that _nlsDcName is available and connected
|
|
|
|
HISTORY: Thomaspa 3/19/96 Created
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER :: CacheTrustedDomains ()
|
|
{
|
|
|
|
APIERR err ;
|
|
|
|
do
|
|
{
|
|
LSA_TRUST_INFO_MEM lsatim ;
|
|
LSA_ENUMERATION_HANDLE lenumHand = 0;
|
|
|
|
if ( err = lsatim.QueryError() )
|
|
break;
|
|
|
|
LSA_POLICY lsapolNew( _nlsDcName.QueryPch(), MAXIMUM_ALLOWED );
|
|
|
|
if ( err = lsapolNew.QueryError() )
|
|
break;
|
|
|
|
STRLIST strlTrustedDomains;
|
|
|
|
NLS_STR nlsTmpDomain;
|
|
|
|
APIERR errEnum;
|
|
|
|
do { // enumeration loop
|
|
|
|
errEnum = lsapolNew.EnumerateTrustedDomains(& lsatim, & lenumHand);
|
|
|
|
if ( errEnum && errEnum != ERROR_MORE_DATA )
|
|
{
|
|
err = errEnum;
|
|
break;
|
|
}
|
|
|
|
if ( err = nlsTmpDomain.QueryError() )
|
|
break;
|
|
|
|
for ( ULONG i = 0 ; i < lsatim.QueryCount() ; i++ )
|
|
{
|
|
if ( err = lsatim.QueryName( i, &nlsTmpDomain ) )
|
|
break; // out of for loop
|
|
|
|
NLS_STR * pnlsTrustedDomain = new NLS_STR( nlsTmpDomain );
|
|
|
|
err = ( pnlsTrustedDomain == NULL ) ? ERROR_NOT_ENOUGH_MEMORY
|
|
: pnlsTrustedDomain->QueryError();
|
|
if ( err )
|
|
break; // out of for loop
|
|
|
|
err = strlTrustedDomains.Append( pnlsTrustedDomain );
|
|
|
|
}
|
|
|
|
if ( err )
|
|
break;
|
|
|
|
} while ( errEnum == ERROR_MORE_DATA );
|
|
|
|
if ( err )
|
|
break;
|
|
|
|
REG_KEY rkLocalMachine( HKEY_LOCAL_MACHINE, GENERIC_READ ) ;
|
|
|
|
NLS_STR nlsNetlogonParms( RGAS_NETLOGON_PARMS );
|
|
|
|
REG_KEY rkNetlogonParms( rkLocalMachine,
|
|
nlsNetlogonParms,
|
|
GENERIC_READ | GENERIC_WRITE ) ;
|
|
|
|
// Remove any old values of the form <domainname>_TrustedDomainList
|
|
// where <domainname> is not the domain we are joining.
|
|
// Don't let errors here stop the join process.
|
|
|
|
REG_ENUM rgEnum( rkNetlogonParms ) ;
|
|
REG_VALUE_INFO_STRUCT rviStruct ;
|
|
static TCHAR abValueData [ maxMultiStrValueSize ] ;
|
|
|
|
rviStruct.pwcData = (BYTE *) abValueData ;
|
|
rviStruct.ulDataLength = sizeof abValueData ;
|
|
|
|
STRLIST strlValuesToDelete;
|
|
while ( rgEnum.NextValue( & rviStruct ) == 0 )
|
|
{
|
|
if ( ::strstrf( rviStruct.nlsValueName.QueryPch(),
|
|
RGAS_VALUE_NETLOGON_TDL_EXT) != NULL )
|
|
{
|
|
NLS_STR * pnlsTmp = new NLS_STR( rviStruct.nlsValueName );
|
|
if ( pnlsTmp && pnlsTmp->QueryError() == 0 )
|
|
strlValuesToDelete.Append( pnlsTmp );
|
|
}
|
|
}
|
|
ITER_STRLIST istrlValuesToDelete( strlValuesToDelete );
|
|
NLS_STR * pnlsValueToDelete ;
|
|
|
|
while ( pnlsValueToDelete = istrlValuesToDelete.Next() )
|
|
{
|
|
rkNetlogonParms.DeleteValue( *pnlsValueToDelete );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Now add the <domainname>_TrustedDomainList value.
|
|
NLS_STR nlsDomainTDL( _nlsDomainName );
|
|
|
|
nlsDomainTDL.Append( RGAS_VALUE_NETLOGON_TDL_EXT );
|
|
|
|
if ( err = nlsDomainTDL.QueryError() )
|
|
break;
|
|
|
|
err = rkNetlogonParms.SetValue( nlsDomainTDL, &strlTrustedDomains );
|
|
|
|
}
|
|
while ( FALSE ) ;
|
|
|
|
return err ;
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::JoinDomain
|
|
|
|
SYNOPSIS: Join an existing domain or set up a new one.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES: Handles the local (LSA) side of domain creation
|
|
or joining.
|
|
|
|
This function and LeaveDomain() do NOT change the
|
|
state of the primary object instance variables
|
|
such as "_fMember".
|
|
|
|
NOTE: The SETUP INF file INITIAL.INF calls the
|
|
SETUPDLL.DLL routine SetAccountDomainSid(). This
|
|
routine generates a random SID and places it into
|
|
both the Accounts domain and the primary domain.
|
|
Thus, for a PDC, we do not need to migrate the
|
|
SID.
|
|
|
|
HISTORY: DavidHov 5/16/92
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER :: JoinDomain ()
|
|
{
|
|
_err = 0;
|
|
|
|
do
|
|
{
|
|
// If not a PDC, join the existing domain.
|
|
|
|
if ( ! _fCreateDomain )
|
|
{
|
|
TRACEEOL( SZ("NCPA/DOMN: Join Domain: ")
|
|
<< _nlsDomainName.QueryPch()
|
|
<< SZ(" password: ")
|
|
<< _nlsComputerAcctPassword.QueryPch() ) ;
|
|
|
|
_err = LSA_POLICY::JoinDomain( _nlsDomainName,
|
|
_nlsComputerAcctPassword,
|
|
_fLanmanNt,
|
|
& _nlsDcName,
|
|
NULL ) ;
|
|
}
|
|
|
|
if ( _err )
|
|
break ;
|
|
|
|
// If joining a domain (non-BDC), then attempt to get the trusted
|
|
// domain list and store it in the registry for Netlogon.
|
|
if ( !_fLanmanNt )
|
|
{
|
|
APIERR err = CacheTrustedDomains() ;
|
|
|
|
TRACEEOL( SZ("NCPA/DOMN: CacheTrustedDomains() reported result ")
|
|
<< err ) ;
|
|
|
|
// Don't allow this block the completion of this operation.
|
|
}
|
|
|
|
// For WinNT, perform secondary domain manipulation
|
|
// operations. This is NOT performed during main
|
|
// installation, beacuse BLDSAM3 performs the same
|
|
// functions when "cross-pollinating" between LSA and
|
|
// the newly initialzed SAM.
|
|
|
|
if ( _fInstall && (! _fLanmanNt) )
|
|
break ;
|
|
|
|
if ( ! (_fLanmanNt || _fInstall) )
|
|
{
|
|
_err = AdjustDomain( TRUE ) ;
|
|
|
|
TRACEEOL( SZ("NCPA/DOMN: Adjust domain after join reported result ")
|
|
<< _err ) ;
|
|
|
|
if ( _err )
|
|
{
|
|
// Don't allow the piddly little stuff to block
|
|
// the completion of this operation.
|
|
|
|
_err = 0 ;
|
|
}
|
|
break ; // Regardless of result, we're done
|
|
}
|
|
|
|
// If LanmanNT PDC, change the name of the primary and
|
|
// accounts domain to the domain name. If this is a BDC,
|
|
// it's already been done by JoinDomain() above.
|
|
|
|
ASSERT( _fLanmanNt ) ;
|
|
|
|
if ( _fCreateDomain )
|
|
{
|
|
TRACEEOL( SZ("NCPA/DOMN: PDC: Setting primary and account domain name to ")
|
|
<< _nlsDomainName.QueryPch() ) ;
|
|
|
|
if ( _err = SetAccountDomainName( & _nlsDomainName ) )
|
|
break ;
|
|
|
|
if ( _err = SetPrimaryDomainName( & _nlsDomainName ) )
|
|
break ;
|
|
}
|
|
else
|
|
{
|
|
// Handle the server role if this is a BDC.
|
|
// Create an owner-allocated BDC LSA server info block and
|
|
// set the server role to BDC.
|
|
|
|
POLICY_LSA_SERVER_ROLE_INFO polsasrim ;
|
|
LSA_SERVER_ROLE_INFO_MEM lsasrim( TRUE ) ;
|
|
|
|
lsasrim.Set( & polsasrim, 1 ) ;
|
|
lsasrim.SetRole( FALSE ) ;
|
|
|
|
if ( (_err = lsasrim.QueryError()) == 0 )
|
|
{
|
|
_err = SetServerRole( & lsasrim ) ;
|
|
}
|
|
|
|
TRACEEOL( SZ("NCPA/DOMN: BDC: Set server role to backup returned: ")
|
|
<< _err ) ;
|
|
}
|
|
}
|
|
while ( FALSE ) ;
|
|
|
|
_fDomainChanged = TRUE ;
|
|
|
|
return _err ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::LeaveDomain
|
|
|
|
SYNOPSIS: Unjoin the current primary domain
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES: This function and TrustDomain() do NOT change the
|
|
state of the primary object instance variables
|
|
such as "_fMember".
|
|
|
|
HISTORY:
|
|
DavidHov 5/16/92 Created
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER :: LeaveDomain ()
|
|
{
|
|
ASSERT( ! (_fInstall || _fLanmanNt) ) ;
|
|
|
|
_err = AdjustDomain( FALSE ) ;
|
|
|
|
TRACEEOL( "NCPA/DOMN: adjust before leaving, result was: "
|
|
<< _err ) ;
|
|
|
|
// The error code above is explictly ignored.
|
|
// This should probably present a popup warning the user
|
|
// to maintain his accounts manually.
|
|
|
|
_err = LSA_POLICY::LeaveDomain() ;
|
|
|
|
TRACEEOL( "NCPA/DOMN: leave domain, result was: "
|
|
<< _err ) ;
|
|
|
|
_fDomainChanged = TRUE ;
|
|
|
|
return _err ;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::QueryCurrentInfo
|
|
|
|
SYNOPSIS: Obtain data necessary for dialog interaction.
|
|
|
|
ENTRY: Nothing
|
|
|
|
EXIT: nothing (see notes)
|
|
|
|
RETURNS: APIERR if failure
|
|
|
|
NOTES: The instance variable are initialized:
|
|
|
|
_fLanmanNt TRUE if LANMan NT product
|
|
is installed
|
|
|
|
_fMember TRUE if machine is domain
|
|
member
|
|
|
|
_nlsUserName name of current user
|
|
|
|
_nlsDomainName if member, name of primary
|
|
domain
|
|
|
|
_nlsWorkgroup if !member, name of workgroup
|
|
|
|
|
|
HISTORY:
|
|
DavidHov 4/6/92 Created
|
|
DavidHov 9/3/92 Removed QueryCurrentUser() call;
|
|
build 311 was broken and it isn't
|
|
extremely useful anyway.
|
|
|
|
********************************************************************/
|
|
#define MOVERRIF(erra,errb) {if ( erra == 0 ) erra = errb;}
|
|
|
|
APIERR DOMAIN_MANAGER :: QueryCurrentInfo ()
|
|
{
|
|
APIERR err = 0,
|
|
nextErr = 0 ;
|
|
LSPL_PROD_TYPE lspl ;
|
|
|
|
// Make a valiant effort to provide all of the information
|
|
// necessary. Save only the first error which occurs,
|
|
// but continue on to obtain as much as possible.
|
|
|
|
do
|
|
{
|
|
nextErr = QueryProductType( & lspl ) ;
|
|
MOVERRIF( err, nextErr );
|
|
|
|
_fLanmanNt = lspl == LSPL_PROD_LANMAN_NT ;
|
|
|
|
_fMember = _fLanmanNt ; // Temporary; see below
|
|
|
|
_nlsLogonUserName = _nlsUserName ;
|
|
|
|
nextErr = QueryPrimaryDomainName( & _nlsDomainName ) ;
|
|
MOVERRIF( err, nextErr );
|
|
|
|
TRACEEOL( SZ("NCPA/DOMMGR: primary domain name: ")
|
|
<< _nlsDomainName.QueryPch() ) ;
|
|
|
|
// If Windows NT, check if the domain name differs from
|
|
// the computer name; if so, we're a member of a non-local
|
|
// domain.
|
|
|
|
if ( !_fLanmanNt )
|
|
{
|
|
nextErr = QueryDomainMember( & _fMember ) ;
|
|
MOVERRIF( err, nextErr );
|
|
}
|
|
|
|
nextErr = QueryPrimaryBrowserGroup( & _nlsWorkgroup ) ;
|
|
MOVERRIF( err, nextErr );
|
|
|
|
TRACEEOL( SZ("NCPA/DOMMGR: query workgroup: ")
|
|
<< _nlsWorkgroup.QueryPch() ) ;
|
|
|
|
} while ( FALSE ) ;
|
|
|
|
return err ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::QueryDomainMember
|
|
|
|
SYNOPSIS:
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER :: QueryDomainMember ( BOOL * pfMember )
|
|
{
|
|
APIERR err = 0 ;
|
|
LSA_PRIMARY_DOM_INFO_MEM lsapdim ;
|
|
|
|
do
|
|
{
|
|
if ( err = lsapdim.QueryError() )
|
|
break ;
|
|
|
|
if ( err = GetPrimaryDomain( & lsapdim ) )
|
|
break ;
|
|
|
|
*pfMember = lsapdim.QueryPSID() != NULL ;
|
|
|
|
#if defined(DEBUG)
|
|
if ( *pfMember )
|
|
{
|
|
TRACEEOL( SZ("NCPA/DOMMGR: Windows/NT machine is a domain member") );
|
|
}
|
|
else
|
|
{
|
|
TRACEEOL( SZ("NCPA/DOMMGR: Windows/NT machine is NOT a domain member") );
|
|
}
|
|
#endif
|
|
}
|
|
while ( FALSE ) ;
|
|
|
|
return err ;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::QueryActiveComputerName
|
|
|
|
SYNOPSIS:
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER ::QueryActiveComputerName
|
|
( NLS_STR * pnlsMachineName ) const
|
|
{
|
|
TCHAR szComputerName [UNCLEN*3] ;
|
|
DWORD dwCch = sizeof szComputerName ;
|
|
APIERR err ;
|
|
|
|
BOOL fOk = ::GetComputerName( szComputerName, & dwCch ) ;
|
|
|
|
if ( fOk )
|
|
{
|
|
szComputerName[dwCch] = 0 ;
|
|
*pnlsMachineName = szComputerName ;
|
|
err = pnlsMachineName->QueryError() ;
|
|
}
|
|
else
|
|
{
|
|
err = ::GetLastError() ;
|
|
}
|
|
return err ;
|
|
}
|
|
|
|
static const WCHAR pszComputerNameKey[] = L"SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ComputerName";
|
|
static const WCHAR pszComputerNameValue[] = L"ComputerName";
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::QueryPendingComputerName
|
|
|
|
SYNOPSIS:
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER ::QueryPendingComputerName
|
|
( NLS_STR * pnlsMachineName ) const
|
|
{
|
|
APIERR err ;
|
|
|
|
HKEY hkeyIntended;
|
|
WCHAR pszTemp[MAX_COMPUTERNAME_LENGTH+1];
|
|
DWORD cbSize;
|
|
DWORD dwType;
|
|
|
|
LONG lrt;
|
|
|
|
// open the keys we need
|
|
do {
|
|
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
pszComputerNameKey,
|
|
0,
|
|
KEY_READ,
|
|
&hkeyIntended );
|
|
if ( err )
|
|
break;
|
|
|
|
// read computer name
|
|
cbSize = sizeof( WCHAR ) * (MAX_COMPUTERNAME_LENGTH + 1);
|
|
err = RegQueryValueEx( hkeyIntended,
|
|
pszComputerNameValue,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)pszTemp,
|
|
&cbSize );
|
|
|
|
RegCloseKey( hkeyIntended );
|
|
|
|
if ( err )
|
|
break;
|
|
|
|
*pnlsMachineName = pszTemp ;
|
|
err = pnlsMachineName->QueryError() ;
|
|
|
|
} while ( FALSE );
|
|
|
|
return err ;
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::SetMachineName
|
|
|
|
SYNOPSIS:
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER ::SetMachineName
|
|
( const NLS_STR & nlsMachineName )
|
|
{
|
|
TRACEEOL( SZ("NCPA/DOMMGR: attempt to change machine name to ")
|
|
<< nlsMachineName.QueryPch() ) ;
|
|
|
|
BOOL fOk = ::SetComputerName( (TCHAR *) nlsMachineName.QueryPch() ) ;
|
|
|
|
_fComputerNameChanged |= fOk ;
|
|
|
|
return fOk ? 0 : GetLastError() ;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::SetWorkgroupName
|
|
|
|
SYNOPSIS: Set the Windows Workgroup name for this
|
|
standalone machine.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES: The WinBall workgroup is implemented by setting the
|
|
name of the primary domain to be the same as that
|
|
of the browsing group to which the user wishes to
|
|
belong.
|
|
|
|
HISTORY: DavidHov 5/26/92 Implemented
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER ::SetWorkgroupName
|
|
( const NLS_STR & nlsWorkgroup )
|
|
{
|
|
TRACEEOL( SZ("NCPA/DOMMGR: setting workgroup name: ")
|
|
<< nlsWorkgroup.QueryPch() ) ;
|
|
|
|
_fDomainChanged = TRUE ;
|
|
|
|
return SetPrimaryDomainName( & nlsWorkgroup ) ;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
//
|
|
// Method:
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes:
|
|
//
|
|
// History:
|
|
// April 21, 1995 MikeMi -
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------
|
|
|
|
APIERR DOMAIN_MANAGER ::DomainChange( BOOL fDomain,
|
|
LPCTSTR pszComputer,
|
|
LPCTSTR pszDomain,
|
|
LPCTSTR pszWorkgroup,
|
|
BOOL fCreate,
|
|
LPCTSTR pszUserName,
|
|
LPCTSTR pszPassword,
|
|
ENUM_WELCOME& fWelcome,
|
|
APIERR& xerr )
|
|
{
|
|
APIERR err = 0;
|
|
BOOL fLeaveDomain;
|
|
BOOL fMember;
|
|
BOOL fIpcActive = FALSE;
|
|
BOOL fLeftStandalone = FALSE;
|
|
BOOL fJustRename = FALSE;
|
|
BOOL fPDC;
|
|
BOOL fBDC;
|
|
NLS_STR nlsOldDomainName( _nlsDomainName );
|
|
NLS_STR nlsOldWorkgroup( _nlsWorkgroup );
|
|
|
|
_err = xerr = 0;
|
|
_fCreateDomain = fPDC = (EROLE_DC == QueryRole());
|
|
fBDC = (EROLE_MEMBER == QueryRole());
|
|
fMember = ((EROLE_TRUSTED == QueryRole()) || fBDC);
|
|
fLeaveDomain = (fMember && !fDomain);
|
|
fWelcome = EWELCOME_NOCHANGE;
|
|
|
|
if ( fCreate && (lstrlen( pszUserName ) > 0) )
|
|
{
|
|
_fUseComputerPassword = FALSE;
|
|
}
|
|
else
|
|
{
|
|
_fUseComputerPassword = TRUE;
|
|
}
|
|
|
|
//
|
|
// validate changes (see ok in dialog class)
|
|
//
|
|
if (fDomain)
|
|
{
|
|
// Check that the domain name entered is valid
|
|
// and is not the same as the computer name.
|
|
|
|
if( !::I_MNetComputerNameCompare( pszDomain, pszComputer ) )
|
|
{
|
|
err = IDS_DOMMGR_NAME_CONFLICT_DOMAIN ;
|
|
}
|
|
}
|
|
|
|
if ( (0 == err) && !fDomain)
|
|
{
|
|
// Check that the workgroup name entered is valid
|
|
// and is not the same as the computer name.
|
|
|
|
if( !::I_MNetComputerNameCompare( pszWorkgroup, pszComputer ) )
|
|
{
|
|
err = IDS_DOMMGR_NAME_CONFLICT_WKGROUP ;
|
|
}
|
|
}
|
|
|
|
if (0 == err)
|
|
{
|
|
//
|
|
// apply changes to ncp object
|
|
//
|
|
|
|
// if member of a domain, set the name
|
|
if (fDomain)
|
|
{
|
|
SetDomainName( pszDomain );
|
|
}
|
|
|
|
// always set workgroup name
|
|
// note that SetWorkgroupName (capitalization) is not what we
|
|
// want to call
|
|
SetWorkGroupName( pszWorkgroup );
|
|
|
|
// did the user supply a name and password
|
|
if (fCreate)
|
|
{
|
|
SetLogonDomainName( pszUserName );
|
|
SetLogonUserName( pszUserName );
|
|
SetQualifiedLogonUserName( pszUserName );
|
|
SetLogonPassword( pszPassword );
|
|
}
|
|
else
|
|
{
|
|
SetComputerAcctPassword();
|
|
}
|
|
|
|
//
|
|
// apply changes to machine
|
|
//
|
|
do
|
|
{
|
|
if (fDomain)
|
|
{
|
|
// just renaming the DC
|
|
if (fPDC)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// are we joining the doman we are a member of
|
|
if ( !_fInstall &&
|
|
fMember &&
|
|
!::I_MNetComputerNameCompare( _nlsDomainName,
|
|
nlsOldDomainName ))
|
|
{
|
|
// no change
|
|
return( 0 );
|
|
}
|
|
|
|
// find the domain
|
|
err = GetDCName();
|
|
if (err)
|
|
{
|
|
err = IDS_DOMMGR_CANT_FIND_DC1;
|
|
SetDomainName( nlsOldDomainName );
|
|
SetWorkGroupName( nlsOldWorkgroup );
|
|
|
|
break;
|
|
}
|
|
|
|
// attempt to NET USE the IPC$ device on the DC.
|
|
// This will use the NULL session if we are using the
|
|
// computer account and password.
|
|
err = UseIPConDC();
|
|
switch (err)
|
|
{
|
|
case 0:
|
|
if (!fCreate)
|
|
{
|
|
err = IDS_NCPA_MACHINE_ACCT_NOT_FOUND;
|
|
fIpcActive = TRUE;
|
|
continue;
|
|
}
|
|
break;
|
|
|
|
case ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT:
|
|
err = 0;
|
|
// In this case, a NULL session will have been created.
|
|
break;
|
|
|
|
case ERROR_NOLOGON_SERVER_TRUST_ACCOUNT:
|
|
// In this case, a NULL session will have been created.
|
|
|
|
if ( !fCreate && !_fLanmanNt )
|
|
{
|
|
// A non-admin is trying to setup up a workstation using a
|
|
// server account. Give an error.
|
|
err = IDS_NCPA_MACHINE_ACCT_INVALID_W ;
|
|
fIpcActive = TRUE;
|
|
continue;
|
|
}
|
|
err = 0;
|
|
break;
|
|
|
|
case IDS_NCPA_DOMAIN_NOT_NT:
|
|
continue;
|
|
|
|
case ERROR_SESSION_CREDENTIAL_CONFLICT:
|
|
err = IDS_DOMMGR_CREDENTIAL_CONFLICT;
|
|
continue;
|
|
|
|
default:
|
|
err = fCreate ? IDS_DOMMGR_CANT_CONNECT_DC
|
|
: IDS_DOMMGR_CANT_CONNECT_DC_PW ;
|
|
continue;
|
|
}
|
|
fIpcActive = TRUE;
|
|
|
|
// leave old domain
|
|
if (fMember && !_fInstall)
|
|
{
|
|
if ( SameDomainSid( _nlsDcName ) )
|
|
{
|
|
fJustRename = TRUE;
|
|
break ;
|
|
}
|
|
else if ( _fLanmanNt ) // it is a BDC
|
|
{
|
|
err = IDS_NCPA_CANT_CHG_BDC_DOMAIN1;
|
|
break;
|
|
}
|
|
else if ( err = LeaveDomain() )
|
|
{
|
|
err = IDS_NCPA_CANT_LEAVE_DOMAIN ;
|
|
break ;
|
|
}
|
|
fMember = FALSE ;
|
|
fLeftStandalone = TRUE;
|
|
|
|
}
|
|
|
|
// Create or change the password on the machine account for
|
|
// this computer on the DC
|
|
if ( err = HandleDomainAccount() )
|
|
{
|
|
if ( err != IDS_NCPA_MACHINE_ACCT_INVALID_W &&
|
|
err != IDS_NCPA_MACHINE_ACCT_INVALID_S &&
|
|
err != IDS_NCPA_MACHINE_ACCT_NOT_FOUND )
|
|
{
|
|
err = IDS_DOMMGR_CANT_ADD_DC_ACCT1;
|
|
}
|
|
}
|
|
}
|
|
} while (FALSE);
|
|
|
|
// The remote side is set up.
|
|
// If we're a member, join the specified domain by creating the
|
|
// shared LSA secret object and trusted domain object.
|
|
|
|
if ((0 == err) && (fDomain || fPDC))
|
|
{
|
|
if ( fJustRename || (fPDC && !_fInstall) )
|
|
{
|
|
err = RenameDomain();
|
|
}
|
|
else
|
|
{
|
|
err = JoinDomain();
|
|
}
|
|
if ( 0 == err )
|
|
{
|
|
_fMember = TRUE ;
|
|
fLeftStandalone = FALSE ;
|
|
fWelcome = EWELCOME_DOMAIN;
|
|
}
|
|
else
|
|
{
|
|
err = IDS_DOMMGR_CANT_JOIN_DOMAIN1;
|
|
}
|
|
|
|
}
|
|
else if (0 == err)
|
|
{
|
|
// leave domain
|
|
if ( fLeaveDomain && !_fInstall )
|
|
{
|
|
if ( err = LeaveDomain() )
|
|
{
|
|
_errMsg = IDS_NCPA_CANT_LEAVE_DOMAIN ;
|
|
}
|
|
else
|
|
{
|
|
_fMember = FALSE ;
|
|
}
|
|
}
|
|
|
|
// join workgroup
|
|
if ( 0 == err && !fDomain && _nlsWorkgroup.QueryTextLength() )
|
|
{
|
|
err = SetWorkgroupName( _nlsWorkgroup ) ;
|
|
if (::I_MNetComputerNameCompare( nlsOldWorkgroup, _nlsWorkgroup ) ||
|
|
(fLeaveDomain) )
|
|
{
|
|
fWelcome = EWELCOME_WORKGROUP;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fLeftStandalone)
|
|
{
|
|
// make sure when we are left stand alone that we have
|
|
// some king of workgroup name
|
|
SetWorkgroupName( nlsOldWorkgroup ) ;
|
|
if (0 == err)
|
|
{
|
|
err = IDS_NCPA_DOMAIN_CHANGE_FAILED_2;
|
|
}
|
|
else
|
|
{
|
|
xerr = err;
|
|
err = IDS_NCPA_DOMAIN_CHANGE_FAILED;
|
|
}
|
|
}
|
|
|
|
// if an error, reset our state from our attempt of change
|
|
if (0 != err)
|
|
{
|
|
QueryCurrentInfo() ;
|
|
}
|
|
|
|
//if (!_fInstall && !fLeftStandalone && (fMember != _fMember))
|
|
if ( (_fInstall) ||
|
|
(!fLeftStandalone && (fMember != _fMember)) )
|
|
{
|
|
APIERR errtemp;
|
|
|
|
// Now change the netlogon start type
|
|
errtemp = AdjustNetlogonStartType( _fMember );
|
|
if ( errtemp != NERR_Success )
|
|
{
|
|
err = IDS_NCPA_CHG_NETLOGON_STARTTYPE;
|
|
}
|
|
else
|
|
{
|
|
errtemp = 0;
|
|
}
|
|
// only use this error if no previous one has happened
|
|
if (0 == err)
|
|
{
|
|
err = errtemp;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fIpcActive)
|
|
{
|
|
disconnectIPC( &_nlsDcName );
|
|
}
|
|
return( err );
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::SameDomainSid
|
|
|
|
SYNOPSIS: Compares the Sid of the existing domain to that
|
|
of the domain the user wishes to join.
|
|
|
|
ENTRY: nlsNewDomain - name of domain to join
|
|
|
|
EXIT: TRUE if the sids match, FALSE otherwise
|
|
|
|
RETURNS:
|
|
|
|
HISTORY: Thomaspa 3/31/92 Created
|
|
|
|
********************************************************************/
|
|
BOOL DOMAIN_MANAGER :: SameDomainSid( const NLS_STR & nlsDcName )
|
|
{
|
|
|
|
// Only need to check the Primary Domain
|
|
LSA_PRIMARY_DOM_INFO_MEM lpdimOrig;
|
|
LSA_PRIMARY_DOM_INFO_MEM lpdimNew;
|
|
|
|
APIERR err = NERR_Success;
|
|
|
|
if ( (err = lpdimOrig.QueryError() )
|
|
|| (err = lpdimNew.QueryError() ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
LSA_POLICY lsapolNew( nlsDcName.QueryPch(), MAXIMUM_ALLOWED );
|
|
if ( (err = lsapolNew.QueryError())
|
|
|| (err = GetPrimaryDomain( &lpdimOrig ) )
|
|
|| (err = lsapolNew.GetPrimaryDomain( &lpdimNew ) ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return ::EqualSid( lpdimOrig.QueryPSID(), lpdimNew.QueryPSID() );
|
|
}
|
|
|
|
#define SERVICE_ACCESS_REQUIRED (GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE)
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::AdjustNetlogonStartType
|
|
|
|
SYNOPSIS: Sets Netlogon to autostart when joining a domain,
|
|
or manual start if leaving a domain
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
HISTORY: Thomaspa 1/28/92 Created
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER :: AdjustNetlogonStartType( BOOL fJoining )
|
|
{
|
|
ASSERT( _pscManager != NULL );
|
|
APIERR err;
|
|
|
|
if ( err = _pscManager->Lock())
|
|
return err;
|
|
|
|
SC_SERVICE ScService( *_pscManager,
|
|
(TCHAR *)SERVICE_NETLOGON,
|
|
SERVICE_ACCESS_REQUIRED ) ;
|
|
|
|
if ( ( err = ScService.QueryError() ) == NERR_Success )
|
|
{
|
|
err = ScService.ChangeConfig( SERVICE_NO_CHANGE,
|
|
fJoining ? SERVICE_AUTO_START
|
|
: SERVICE_DEMAND_START,
|
|
SERVICE_NO_CHANGE );
|
|
}
|
|
|
|
_pscManager->Unlock();
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: DOMAIN_MANAGER::SetDefaultWorkgroupName
|
|
|
|
SYNOPSIS: Loads the default workgroup name from the
|
|
resource fork.
|
|
|
|
ENTRY:
|
|
|
|
EXIT:
|
|
|
|
RETURNS:
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
|
|
********************************************************************/
|
|
APIERR DOMAIN_MANAGER :: SetDefaultWorkgroupName ()
|
|
{
|
|
WCHAR szTemp[MAX_DOMAINNAME_LENGTH+1];
|
|
int err;
|
|
APIERR apierr = 0;
|
|
|
|
err = LoadString( g_hinst, IDS_NCPA_DEFAULT_WORKGROUP, szTemp, MAX_DOMAINNAME_LENGTH );
|
|
if (err)
|
|
{
|
|
_nlsWorkgroup = szTemp;
|
|
}
|
|
else
|
|
{
|
|
apierr = GetLastError();
|
|
}
|
|
// return _nlsWorkgroup.Load( IDS_NCPA_DEFAULT_WORKGROUP ) ;
|
|
return( apierr );
|
|
}
|
|
|
|
// End of NCPADOMN.CXX
|
|
|
|
|