238 lines
6.1 KiB
C
238 lines
6.1 KiB
C
/*--
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
setprefdc.c
|
|
|
|
Abstract:
|
|
|
|
Program to set the preferred trusted DC to a particular DC.
|
|
|
|
Author:
|
|
|
|
13-Mar-1997 (Cliff Van Dyke)
|
|
|
|
--*/
|
|
|
|
#define UNICODE 1
|
|
#include <windows.h>
|
|
#include <shellapi.h>
|
|
#include <lmcons.h>
|
|
#include <lmerr.h>
|
|
#include <lmapibuf.h>
|
|
#include <lmaccess.h>
|
|
#include <lmuse.h>
|
|
#include <stdio.h>
|
|
|
|
#define OneStatus( _x ) \
|
|
case _x: \
|
|
fprintf( stderr, #_x "\n" ); \
|
|
break;
|
|
|
|
VOID
|
|
PrintError( NET_API_STATUS NetStatus )
|
|
{
|
|
switch ( NetStatus ) {
|
|
OneStatus(ERROR_NO_SUCH_DOMAIN);
|
|
OneStatus(ERROR_BAD_NETPATH);
|
|
OneStatus(ERROR_ACCESS_DENIED);
|
|
OneStatus(ERROR_NOT_SUPPORTED);
|
|
OneStatus(ERROR_NO_TRUST_SAM_ACCOUNT);
|
|
OneStatus(ERROR_NO_TRUST_LSA_SECRET);
|
|
OneStatus(ERROR_TRUSTED_DOMAIN_FAILURE);
|
|
OneStatus(ERROR_TRUSTED_RELATIONSHIP_FAILURE);
|
|
OneStatus(ERROR_NETLOGON_NOT_STARTED);
|
|
OneStatus(NO_ERROR);
|
|
default:
|
|
fprintf( stderr, "%ld\n", NetStatus );
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
_cdecl
|
|
main(int argc, char **argv)
|
|
{
|
|
NET_API_STATUS NetStatus;
|
|
LPWSTR CommandLine;
|
|
LPWSTR *argvw;
|
|
int argcw;
|
|
LPWSTR ServerName = NULL; // Make local calls
|
|
LPWSTR TrustedDomainName;
|
|
PNETLOGON_INFO_2 OrigNetlogonInfo2 = NULL;
|
|
PNETLOGON_INFO_2 NewNetlogonInfo2 = NULL;
|
|
USE_INFO_2 UseInfo2;
|
|
int i;
|
|
|
|
WCHAR UncDcName[UNCLEN+1];
|
|
WCHAR ShareName[UNCLEN+1+NNLEN+1];
|
|
WCHAR NewDomainAndDc[DNLEN+1+CNLEN+1];
|
|
LPWSTR NewDomainAndDcPtr;
|
|
LPWSTR DcName;
|
|
ULONG DcNameLen;
|
|
|
|
//
|
|
// Get the command line in Unicode
|
|
//
|
|
|
|
CommandLine = GetCommandLine();
|
|
|
|
argvw = CommandLineToArgvW( CommandLine, &argcw );
|
|
|
|
if ( argvw == NULL ) {
|
|
fprintf( stderr, "Can't convert command line to Unicode: %ld\n", GetLastError() );
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
// Get the arguments
|
|
//
|
|
if ( argcw < 3 ) {
|
|
Usage:
|
|
fprintf( stderr, "Usage: %s <TrustedDomain> <ListOfDcsInTrustedDomain>\n", argv[0]);
|
|
return 1;
|
|
}
|
|
TrustedDomainName = argvw[1];
|
|
_wcsupr( TrustedDomainName );
|
|
|
|
|
|
//
|
|
// Query the secure channel to find out the current DC being used.
|
|
//
|
|
|
|
NetStatus = I_NetLogonControl2( ServerName,
|
|
NETLOGON_CONTROL_TC_QUERY,
|
|
2,
|
|
(LPBYTE) &TrustedDomainName,
|
|
(LPBYTE *)&OrigNetlogonInfo2 );
|
|
|
|
if ( NetStatus != NERR_Success ) {
|
|
fprintf( stderr, "Cannot determine current trusted DC of domain '%ws': ", TrustedDomainName );
|
|
PrintError( NetStatus );
|
|
return 1;
|
|
}
|
|
|
|
|
|
//
|
|
// Loop handling each preferred DC.
|
|
//
|
|
|
|
for ( i=2; i<argcw; i++ ) {
|
|
|
|
//
|
|
// Grab the DC name specified by the caller.
|
|
//
|
|
|
|
DcName = argvw[i];
|
|
_wcsupr( DcName );
|
|
if ( DcName[0] == L'\\' && DcName[1] == L'\\' ) {
|
|
DcName += 2;
|
|
}
|
|
DcNameLen = wcslen(DcName);
|
|
if ( DcNameLen < 1 || DcNameLen > CNLEN ) {
|
|
fprintf( stderr, "DcName '%ws' is invalid.\n", DcName );
|
|
goto Usage;
|
|
}
|
|
wcscpy( UncDcName, L"\\\\" );
|
|
wcscat( UncDcName, DcName );
|
|
|
|
//
|
|
// If the named DC is already the current DC,
|
|
// just tell the caller.
|
|
//
|
|
|
|
if ( OrigNetlogonInfo2->netlog2_trusted_dc_name != NULL &&
|
|
_wcsicmp( OrigNetlogonInfo2->netlog2_trusted_dc_name,
|
|
UncDcName) == 0 ) {
|
|
fprintf( stderr, "DC already is '%ws'.\n", UncDcName );
|
|
return 0;
|
|
}
|
|
|
|
|
|
//
|
|
// Test if this DC is up.
|
|
//
|
|
|
|
wcscpy( ShareName, UncDcName );
|
|
wcscat( ShareName, L"\\IPC$" );
|
|
|
|
UseInfo2.ui2_local = NULL;
|
|
UseInfo2.ui2_remote = ShareName;
|
|
UseInfo2.ui2_password = NULL;
|
|
UseInfo2.ui2_asg_type = USE_IPC;
|
|
UseInfo2.ui2_username = NULL;
|
|
UseInfo2.ui2_domainname = NULL;
|
|
|
|
NetStatus = NetUseAdd( NULL, 2, (LPBYTE) &UseInfo2, NULL );
|
|
|
|
if ( NetStatus == NERR_Success ) {
|
|
NetStatus = NetUseDel( NULL, ShareName, FALSE );
|
|
|
|
if ( NetStatus != NERR_Success ) {
|
|
fprintf( stderr, "Cannot remove connection to '%ws' (Continuing): ", UncDcName );
|
|
PrintError( NetStatus );
|
|
}
|
|
|
|
} else if ( NetStatus == ERROR_ACCESS_DENIED ) {
|
|
/* Server really is up */
|
|
} else if ( NetStatus == ERROR_SESSION_CREDENTIAL_CONFLICT ) {
|
|
/* We can only assume the server is up */
|
|
} else {
|
|
fprintf( stderr, "Cannot connect to '%ws': ", UncDcName );
|
|
PrintError( NetStatus );
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// This DC is up. Try to use it.
|
|
//
|
|
|
|
wcscpy( NewDomainAndDc, TrustedDomainName );
|
|
wcscat( NewDomainAndDc, L"\\" );
|
|
wcscat( NewDomainAndDc, UncDcName+2 );
|
|
NewDomainAndDcPtr = NewDomainAndDc;
|
|
|
|
NetStatus = I_NetLogonControl2( ServerName,
|
|
NETLOGON_CONTROL_REDISCOVER,
|
|
2,
|
|
(LPBYTE) &NewDomainAndDcPtr,
|
|
(LPBYTE *)&NewNetlogonInfo2 );
|
|
|
|
if ( NetStatus != NERR_Success ) {
|
|
fprintf( stderr, "Cannot set new trusted DC to '%ws': ", UncDcName );
|
|
PrintError( NetStatus );
|
|
continue;
|
|
}
|
|
|
|
|
|
//
|
|
// If the named DC is now the DC,
|
|
// tell the caller.
|
|
//
|
|
|
|
if ( NewNetlogonInfo2->netlog2_trusted_dc_name != NULL &&
|
|
_wcsicmp( NewNetlogonInfo2->netlog2_trusted_dc_name,
|
|
UncDcName) == 0 ) {
|
|
fprintf( stderr, "Successfully set DC to '%ws'.\n", UncDcName );
|
|
return 0;
|
|
}
|
|
|
|
fprintf( stderr,
|
|
"Cannot set trusted DC to '%ws' it is '%ws': \n",
|
|
UncDcName,
|
|
NewNetlogonInfo2->netlog2_trusted_dc_name,
|
|
NewNetlogonInfo2->netlog2_tc_connection_status );
|
|
PrintError( NetStatus );
|
|
|
|
}
|
|
|
|
fprintf( stderr, "Failed to set the DC.\n" );
|
|
|
|
return 1;
|
|
}
|
|
|
|
|