WindowsXP-SP1/ds/netapi/netdom/time.cxx

1125 lines
29 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Microsoft Windows
Copyright (C) Microsoft Corporation, 1998 - 2001
Module Name:
time.c
Abstract:
Handles the various functions for the time functionality of netdom
--*/
#include "pch.h"
#pragma hdrstop
#include <netdom.h>
DWORD
NetDompTimeGetDc(
IN PWSTR Domain,
IN PWSTR DestServer,
IN PND5_AUTH_INFO AuthInfo,
OUT PWSTR *Dc
)
/*++
Routine Description:
This function will find the DC to use as a time source for the given machine
Arguments:
Domain - Domain to get a time source from
DestServer - Server for which we need a time source
AuthInfo - Auth info to connect to the destination server for
Dc - Where the dc name is returned. Freed via NetApiBufferFree
Return Value:
ERROR_INVALID_PARAMETER - No object name was supplied
--*/
{
DWORD Win32Err = ERROR_SUCCESS;
PDOMAIN_CONTROLLER_INFO DcInfo = NULL;
BOOL Retry = FALSE;
WCHAR FlatName[ CNLEN + 1 ];
ULONG Len = CNLEN + 1;
//
// Get a server name
//
Win32Err = DsGetDcName( NULL,
Domain,
NULL,
NULL,
DS_GOOD_TIMESERV_PREFERRED,
&DcInfo );
//
// If we have a destination server specified, make sure that we
// aren't talking to ourselves... That would kind of defeat the purpose
//
if ( Win32Err == ERROR_SUCCESS && DestServer ) {
if ( !_wcsicmp( DcInfo->DomainControllerName + 2, DestServer ) ) {
Retry = TRUE;
} else {
//
// Handle the case where we have a Dns dc name and a netbios server name
//
if ( wcslen( DestServer ) <= CNLEN && FLAG_ON( DcInfo->Flags, DS_IS_DNS_NAME ) ) {
if ( !DnsHostnameToComputerName( DcInfo->DomainControllerName + 2,
FlatName,
&Len ) ) {
Win32Err = GetLastError();
} else {
if ( !_wcsicmp( FlatName, DestServer ) ) {
Retry = TRUE;
}
}
}
}
}
//
// We have a dc name specified, so connect to that machine, and try it again, with
// the AvoidSelf flag. If we can't (like this is an NT4 PDC) then return that we
// can't find a dc
//
if ( Win32Err == ERROR_SUCCESS && Retry ) {
NetApiBufferFree( DcInfo );
DcInfo = NULL;
Win32Err = NetpManageIPCConnect( DestServer,
AuthInfo->User,
AuthInfo->Password,
NETSETUPP_CONNECT_IPC );
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = DsGetDcName( DestServer,
Domain,
NULL,
NULL,
DS_GOOD_TIMESERV_PREFERRED | DS_AVOID_SELF,
&DcInfo );
NetpManageIPCConnect( DestServer,
AuthInfo->User,
AuthInfo->Password,
NETSETUPP_DISCONNECT_IPC );
}
}
//
// Copy the name if everything worked
//
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = NetApiBufferAllocate( ( wcslen( DcInfo->DomainControllerName + 2 ) + 1 ) *
sizeof( WCHAR ),
(PVOID*)Dc );
if ( Win32Err == ERROR_SUCCESS ) {
wcscpy( *Dc, DcInfo->DomainControllerName + 2 );
}
}
NetApiBufferFree( DcInfo );
return( Win32Err );
}
DWORD
NetDompEnableSystimePriv(
VOID
)
/*++
Routine Description:
This function will enable the systemtime privilege for the current thread
Arguments:
VOID
Return Value:
ERROR_INVALID_PARAMETER - No object name was supplied
--*/
{
NTSTATUS Status;
HANDLE ThreadToken;
TOKEN_PRIVILEGES Enabled, Previous;
DWORD PreviousSize;
Status = NtOpenThreadToken( NtCurrentThread(),
TOKEN_READ | TOKEN_WRITE,
TRUE,
&ThreadToken );
if ( Status == STATUS_NO_TOKEN ) {
Status = NtOpenProcessToken( NtCurrentProcess(),
TOKEN_WRITE | TOKEN_READ,
&ThreadToken );
}
if ( NT_SUCCESS( Status ) ) {
Enabled.PrivilegeCount = 1;
Enabled.Privileges[0].Luid.LowPart = SE_SYSTEMTIME_PRIVILEGE;
Enabled.Privileges[0].Luid.HighPart = 0;
Enabled.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
PreviousSize = sizeof( Previous );
Status = NtAdjustPrivilegesToken( ThreadToken,
FALSE,
&Enabled,
sizeof( Enabled ),
&Previous,
&PreviousSize );
}
return( RtlNtStatusToDosError( Status ) );
}
DWORD
NetDompGetTimeTripLength(
IN PWSTR Server,
IN OUT PDWORD TripLength
)
/*++
Routine Description:
This function will get an approximate elapsed time for getting the time from a domain
controller
Arguments:
Server - Server to get the elapsed trip time for
TripLength - Number of ticks it takes to get the time
Return Value:
ERROR_SUCCESS - The function succeeded
--*/
{
DWORD Win32Err = ERROR_SUCCESS;
ULONG StartTime, EndTime, ElapsedTime = 0, i;
PTIME_OF_DAY_INFO TOD;
#define NETDOMP_NUM_TRIPS 2
//
// Get the average from several time trips
//
for ( i = 0; i < NETDOMP_NUM_TRIPS && Win32Err == ERROR_SUCCESS; i++ ) {
StartTime = GetTickCount();
Win32Err = NetRemoteTOD( Server, ( LPBYTE * )&TOD );
EndTime = GetTickCount();
ElapsedTime += ( EndTime - StartTime );
NetApiBufferFree( TOD );
}
if ( Win32Err == ERROR_SUCCESS ) {
*TripLength = ElapsedTime / NETDOMP_NUM_TRIPS;
}
return( Win32Err );
}
DWORD
NetDompResetSingleClient(
IN PWSTR Server,
IN PWSTR Dc,
IN PND5_AUTH_INFO ObjectAuthInfo,
IN DWORD DcDelay
)
/*++
Routine Description:
This function sync the time between and NT5 client and the specified domain controller
Arguments:
Server - Server to reset the time for
Dc - Domain controller to sync the time against
ObjectAuthInfo - User info to connect to the server as
DcDelay - The amount of time it takes to talk to the dc
Return Value:
ERROR_SUCCESS - The function succeeded
--*/
{
DWORD Win32Err = ERROR_SUCCESS;
BOOL Connected = FALSE;
//PSTR ServerA = NULL;
//
// Set up a connection to the client machine
//
Win32Err = NetpManageIPCConnect( Server,
ObjectAuthInfo->User,
ObjectAuthInfo->Password,
NETSETUPP_CONNECT_IPC );
if ( Win32Err == ERROR_SUCCESS ) {
Connected = TRUE;
} else {
goto ResetSingleError;
}
//if ( Server ) {
//
// Win32Err = NetApiBufferAllocate( wcstombs( NULL, Server, wcslen( Server ) + 1 ) + 3,
// &ServerA );
// if ( Win32Err != ERROR_SUCCESS ) {
//
// goto ResetSingleError;
// }
//
// if ( *Server == L'\\' ) {
//
// strcpy( ServerA, "\\\\" );
// wcstombs( ServerA + 2, Server, wcslen( Server ) + 1 );
//
// } else {
//
// wcstombs( ServerA, Server, wcslen( Server ) + 1 );
// }
//}
Win32Err = W32TimeSyncNow( Server,
FALSE, // no wait
TimeSyncFlag_HardResync );
ResetSingleError:
if ( Connected ) {
NetpManageIPCConnect( Server,
ObjectAuthInfo->User,
ObjectAuthInfo->Password,
NETSETUPP_DISCONNECT_IPC );
}
//NetApiBufferFree( ServerA );
return( Win32Err );
}
DWORD
NetDompVerifySingleClient(
IN PWSTR Server,
IN PWSTR Dc,
IN PND5_AUTH_INFO ObjectAuthInfo,
IN DWORD DcDelay,
IN BOOL * InSync
)
/*++
Routine Description:
This function will verify that the time between the specified server and domain controller
is within the acceptable skew
Arguments:
Server - Server to verify the time for
Dc - Domain controller to verify the time against
ObjectAuthInfo - User and password to connect to the client as
DcDelay - How long does it take to get the time from the domain controller
InSync - Where the results are returned.
Return Value:
ERROR_SUCCESS - The function succeeded
--*/
{
DWORD Win32Err = ERROR_SUCCESS;
SYSTEMTIME StartTime, EndTime;
PTIME_OF_DAY_INFO DcTOD = NULL, ClientTOD = NULL;
BOOL Connected = FALSE;
FILETIME StartFile, EndFile;
LARGE_INTEGER ElapsedTime, TimeDifference, DcTime, ClientTime, UpdatedDcTime, TimeSkew,
AllowedSkew;
TIME_FIELDS TimeFields;
LARGE_INTEGER SystemTime;
//
// Set the allowable time skew. 600,000,000L is the number of 100 nanoseconds in a minute
//
#define NETDOMP_VERIFY_SKEW 0xB2D05E00
//
// Assume the clocks are fine
//
*InSync = TRUE;
//
// Set up a connection to the client machine
//
Win32Err = NetpManageIPCConnect( Server,
ObjectAuthInfo->User,
ObjectAuthInfo->Password,
NETSETUPP_CONNECT_IPC );
if ( Win32Err == ERROR_SUCCESS ) {
Connected = TRUE;
} else {
goto VerifySingleError;
}
//
// Ok, first, we get the time on the dc, then we get the time on the client, keeping in mind
// how long that takes,
//
Win32Err = NetRemoteTOD( Dc, ( LPBYTE * )&DcTOD );
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = NetRemoteTOD( Server, ( LPBYTE * )&ClientTOD );
}
if ( Win32Err != ERROR_SUCCESS ) {
goto VerifySingleError;
}
//
// Ok, now we've gotten all the info we need, assemble it... Note that we are only computing
// the difference in time here...
//
SystemTimeToFileTime( &StartTime, &StartFile );
SystemTimeToFileTime( &EndTime, &EndFile );
ElapsedTime = RtlLargeIntegerSubtract( *( PLARGE_INTEGER )&EndFile,
*( PLARGE_INTEGER )&StartFile );
TimeFields.Hour = ( WORD )DcTOD->tod_hours;
TimeFields.Minute = ( WORD )DcTOD->tod_mins;
TimeFields.Second = ( WORD )DcTOD->tod_secs;
TimeFields.Milliseconds = ( WORD )DcTOD->tod_hunds * 10;
TimeFields.Day = ( WORD )DcTOD->tod_day;
TimeFields.Month = ( WORD )DcTOD->tod_month;
TimeFields.Year = ( WORD )DcTOD->tod_year;
if ( !RtlTimeFieldsToTime( &TimeFields, &DcTime ) ) {
Win32Err = ERROR_INVALID_PARAMETER;
}
TimeFields.Hour = ( WORD )ClientTOD->tod_hours;
TimeFields.Minute = ( WORD )ClientTOD->tod_mins;
TimeFields.Second = ( WORD )ClientTOD->tod_secs;
TimeFields.Milliseconds = ( WORD )ClientTOD->tod_hunds * 10;
TimeFields.Day = ( WORD )ClientTOD->tod_day;
TimeFields.Month = ( WORD )ClientTOD->tod_month;
TimeFields.Year = ( WORD )ClientTOD->tod_year;
if ( !RtlTimeFieldsToTime( &TimeFields, &ClientTime ) ) {
Win32Err = ERROR_INVALID_PARAMETER;
}
//
// Add the time it takes to get the time from the dc.
//
UpdatedDcTime = RtlLargeIntegerAdd( DcTime, ElapsedTime );
//
// Compute the difference in time
//
if ( RtlLargeIntegerGreaterThan( UpdatedDcTime, ClientTime ) ) {
TimeSkew = RtlLargeIntegerSubtract( UpdatedDcTime,
ClientTime );
} else {
TimeSkew = RtlLargeIntegerSubtract( ClientTime,
UpdatedDcTime );
}
//
// Now, see if there is a time difference greater than the allowable skew
//
AllowedSkew = RtlConvertUlongToLargeInteger( NETDOMP_VERIFY_SKEW );
if ( RtlLargeIntegerGreaterThan( TimeSkew, AllowedSkew ) ) {
*InSync = FALSE;
}
VerifySingleError:
if ( Connected ) {
NetpManageIPCConnect( Server,
ObjectAuthInfo->User,
ObjectAuthInfo->Password,
NETSETUPP_DISCONNECT_IPC );
}
NetApiBufferFree( ClientTOD );
NetApiBufferFree( DcTOD );
return( Win32Err );
}
VOID
NetDompDisplayTimeVerify(
IN PWSTR Server,
IN DWORD Results,
IN BOOL InSync
)
/*++
Routine Description:
This function will display the results of the time verification
Arguments:
Server - Server which had the time verified
Results - The error code of the verification attempt
InSync - Whether the clocks are within the skew. Only valid if Results is ERROR_SUCCESS
Return Value:
VOID
--*/
{
NetDompDisplayMessage( MSG_TIME_COMPUTER, Server );
if ( Results != ERROR_SUCCESS ) {
NetDompDisplayErrorMessage( Results );
} else {
NetDompDisplayMessage( InSync ? MSG_TIME_SUCCESS : MSG_TIME_FAILURE );
}
}
DWORD
NetDompVerifyTime(
IN PWSTR Domain,
IN PWSTR Server, OPTIONAL
IN PND5_AUTH_INFO DomainAuthInfo,
IN PND5_AUTH_INFO ObjectAuthInfo,
IN PWSTR Dc,
IN BOOL AllWorkstation,
IN BOOL AllServer
)
/*++
Routine Description:
This function will verify the time between some or all of the servers/workstations in a
domain against the specified domain controller
Arguments:
Domain - Domain containing the servers/workstations
Server - Name of a specific machine to verify the time for
DomainAuthInfo - User and password for the domain controller
ObjectAuthInfo - User and password for the servers/workstations
Dc - Name of a domain controller in the domain to use as a time source
AllWorkstation - If TRUE, verify the time for all the workstations
AllServer - If TRUE, verify the time for all the servers
Return Value:
ERROR_SUCCESS - The function succeeded
ERROR_INVALID_PARAMETER - No server, workstation or machine was specified
--*/
{
DWORD Win32Err = ERROR_SUCCESS, Err2;
BOOL DcSession = FALSE, InSync;
DWORD DcDelay;
LPUSER_INFO_0 UserList = NULL;
PWSTR FullDc = NULL, Lop;
ULONG ResumeHandle = 0, Count = 0, TotalCount = 0, i, j;
ULONG Types[] = {
FILTER_WORKSTATION_TRUST_ACCOUNT,
FILTER_SERVER_TRUST_ACCOUNT
};
BOOL ProcessType[ sizeof( Types ) / sizeof( ULONG ) ];
ProcessType[ 0 ] = AllWorkstation;
ProcessType[ 1 ] = AllServer;
//
// Make sure that there is something to do
//
if ( !Server && !AllWorkstation && !AllServer ) {
return( ERROR_INVALID_PARAMETER );
}
//
// Build a full machine name
//
if ( Dc && *Dc != L'\\' ) {
Win32Err = NetApiBufferAllocate( ( wcslen( Dc ) + 3 ) * sizeof( WCHAR ),
( PVOID * )&FullDc );
if ( Win32Err == ERROR_SUCCESS ) {
swprintf( FullDc, L"\\\\%ws", Dc );
}
} else {
FullDc = Dc;
}
//
// Set up a session
//
Win32Err = NetpManageIPCConnect( FullDc,
DomainAuthInfo->User,
DomainAuthInfo->Password,
NETSETUPP_CONNECT_IPC );
if ( Win32Err == ERROR_SUCCESS ) {
DcSession = FALSE;
}
//
// See how long it takes to get to the dc
//
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = NetDompGetTimeTripLength( Dc,
&DcDelay );
}
if ( Win32Err != ERROR_SUCCESS ) {
goto VerifyTimeError;
}
NetDompDisplayMessage( MSG_TIME_VERIFY );
//
// Verify a single machine
//
if ( Server ) {
Win32Err = NetDompVerifySingleClient( Server,
Dc,
ObjectAuthInfo,
DcDelay,
&InSync );
NetDompDisplayTimeVerify( Server,
Win32Err,
InSync );
}
//
// Verify all the workstations/servers, if requested.
//
for ( i = 0; i < sizeof( Types ) / sizeof( ULONG ); i++ ) {
if ( !ProcessType[ i ] ) {
continue;
}
do {
Win32Err = NetUserEnum( FullDc,
0,
Types[ i ],
( LPBYTE * )&UserList,
MAX_PREFERRED_LENGTH,
&Count,
&TotalCount,
&ResumeHandle );
if ( Win32Err == ERROR_SUCCESS || Win32Err == ERROR_MORE_DATA ) {
for ( j = 0; j < Count; j++ ) {
Lop = wcsrchr( UserList[ j ].usri0_name, L'$' );
if ( Lop ) {
*Lop = UNICODE_NULL;
}
Err2 = NetDompVerifySingleClient( UserList[ j ].usri0_name,
Dc,
ObjectAuthInfo,
DcDelay,
&InSync );
NetDompDisplayTimeVerify( UserList[ j ].usri0_name,
Err2,
InSync );
}
NetApiBufferFree( UserList );
}
} while ( Win32Err == ERROR_MORE_DATA );
}
VerifyTimeError:
if ( DcSession ) {
NetpManageIPCConnect( FullDc,
DomainAuthInfo->User,
DomainAuthInfo->Password,
NETSETUPP_DISCONNECT_IPC );
}
if ( FullDc != Dc ) {
NetApiBufferFree( FullDc );
}
return( Win32Err );
}
DWORD
NetDompResetTime(
IN PWSTR Domain,
IN PWSTR Server, OPTIONAL
IN PND5_AUTH_INFO DomainAuthInfo,
IN PND5_AUTH_INFO ObjectAuthInfo,
IN PWSTR Dc,
IN BOOL AllWorkstation,
IN BOOL AllServer
)
/*++
Routine Description:
This function will reset the time between some or all of the servers/workstations in a
domain against the specified domain controller
Arguments:
Domain - Domain containing the servers/workstations
Server - Name of a specific machine to reset the time for
DomainAuthInfo - User and password for the domain controller
ObjectAuthInfo - User and password for the servers/workstations
Dc - Name of a domain controller in the domain to use as a time source
AllWorkstation - If TRUE, reset the time for all the workstations
AllServer - If TRUE, reset the time for all the servers
Return Value:
ERROR_SUCCESS - The function succeeded
ERROR_INVALID_PARAMETER - No server, workstation or machine was specified
--*/
{
DWORD Win32Err = ERROR_SUCCESS, Err2;
BOOL DcSession = FALSE, InSync;
DWORD DcDelay;
LPUSER_INFO_0 UserList = NULL;
PWSTR FullDc = NULL, Lop;
ULONG ResumeHandle = 0, Count = 0, TotalCount = 0, i, j;
ULONG Types[] = {
FILTER_WORKSTATION_TRUST_ACCOUNT,
FILTER_SERVER_TRUST_ACCOUNT
};
BOOL ProcessType[ sizeof( Types ) / sizeof( ULONG ) ];
ProcessType[ 0 ] = AllWorkstation;
ProcessType[ 1 ] = AllServer;
//
// Make sure that there is something to do
//
if ( !Server && !AllWorkstation && !AllServer ) {
return( ERROR_INVALID_PARAMETER );
}
if ( Dc && *Dc != L'\\' ) {
Win32Err = NetApiBufferAllocate( ( wcslen( Dc ) + 3 ) * sizeof( WCHAR ),
( PVOID * )&FullDc );
if ( Win32Err == ERROR_SUCCESS ) {
swprintf( FullDc, L"\\\\%ws", Dc );
}
} else {
FullDc = Dc;
}
Win32Err = NetpManageIPCConnect( FullDc,
DomainAuthInfo->User,
DomainAuthInfo->Password,
NETSETUPP_CONNECT_IPC );
if ( Win32Err == ERROR_SUCCESS ) {
DcSession = FALSE;
}
//
// Get the trip time to the dc
//
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = NetDompGetTimeTripLength( Dc,
&DcDelay );
}
if ( Win32Err != ERROR_SUCCESS ) {
goto ResetTimeError;
}
NetDompDisplayMessage( MSG_TIME_VERIFY );
//
// Reset the client, if needed
//
if ( Server ) {
Win32Err = NetDompVerifySingleClient( Server,
Dc,
ObjectAuthInfo,
DcDelay,
&InSync );
if ( Win32Err == ERROR_SUCCESS && !InSync ) {
Win32Err = NetDompResetSingleClient( Server,
Dc,
ObjectAuthInfo,
DcDelay );
}
}
//
// Do all the workstations/servers, if required
//
for ( i = 0; i < sizeof( Types ) / sizeof( ULONG ); i++ ) {
if ( !ProcessType[ i ] ) {
continue;
}
do {
Win32Err = NetUserEnum( FullDc,
0,
Types[ i ],
( LPBYTE * )&UserList,
MAX_PREFERRED_LENGTH,
&Count,
&TotalCount,
&ResumeHandle );
if ( Win32Err == ERROR_SUCCESS || Win32Err == ERROR_MORE_DATA ) {
for ( j = 0; j < Count; j++ ) {
Lop = wcsrchr( UserList[ j ].usri0_name, L'$' );
if ( Lop ) {
*Lop = UNICODE_NULL;
}
Err2 = NetDompVerifySingleClient( UserList[ j ].usri0_name,
Dc,
ObjectAuthInfo,
DcDelay,
&InSync );
if ( Err2 == ERROR_SUCCESS && !InSync ) {
Err2 = NetDompResetSingleClient( UserList[ j ].usri0_name,
Dc,
ObjectAuthInfo,
DcDelay );
}
}
NetApiBufferFree( UserList );
}
} while ( Win32Err == ERROR_MORE_DATA );
}
ResetTimeError:
if ( DcSession ) {
NetpManageIPCConnect( FullDc,
DomainAuthInfo->User,
DomainAuthInfo->Password,
NETSETUPP_DISCONNECT_IPC );
}
if ( FullDc != Dc ) {
NetApiBufferFree( FullDc );
}
return( Win32Err );
}
DWORD
NetDompHandleTime(ARG_RECORD * rgNetDomArgs)
/*++
Routine Description:
This function will handle the NETDOM TIME requirements
Arguments:
Args - List of command line arguments
Return Value:
ERROR_INVALID_PARAMETER - No object name was supplied
--*/
{
DWORD Win32Err = ERROR_SUCCESS;
PWSTR Domain = NULL, Dc = NULL;
ND5_AUTH_INFO DomainUser, ObjectUser;
ULONG i;
PWSTR Object = rgNetDomArgs[eObject].strValue;
if (!Object)
{
DisplayHelp(ePriTime);
return( ERROR_INVALID_PARAMETER );
}
RtlZeroMemory( &DomainUser, sizeof( ND5_AUTH_INFO ) );
RtlZeroMemory( &ObjectUser, sizeof( ND5_AUTH_INFO ) );
//
// Validate the args
//
Win32Err = NetDompValidateSecondaryArguments(rgNetDomArgs,
eObject,
eCommDomain,
eCommUserNameO,
eCommPasswordO,
eCommUserNameD,
eCommPasswordD,
eQueryServer,
eQueryWksta,
eCommVerify,
eCommReset,
eCommVerbose,
eArgEnd);
if ( Win32Err != ERROR_SUCCESS ) {
DisplayHelp(ePriTime);
goto HandleTimeExit;
}
//
// Verify that we don't have too many arguments
//
if ( CmdFlagOn(rgNetDomArgs, eCommVerify) &&
CmdFlagOn(rgNetDomArgs, eCommReset) ) {
NetDompDisplayUnexpectedParameter(rgNetDomArgs[eCommReset].strArg1);
Win32Err = ERROR_INVALID_PARAMETER;
goto HandleTimeExit;
}
//
// Ok, make sure that we have a specified domain...
//
Win32Err = NetDompGetDomainForOperation(rgNetDomArgs,
Object,
TRUE,
&Domain);
if ( Win32Err != ERROR_SUCCESS ) {
goto HandleTimeExit;
}
//
// Get the password and user if it exists
//
if ( CmdFlagOn(rgNetDomArgs, eCommUserNameD) ) {
Win32Err = NetDompGetUserAndPasswordForOperation(rgNetDomArgs,
eCommUserNameD,
Domain,
&DomainUser);
if ( Win32Err != ERROR_SUCCESS ) {
goto HandleTimeExit;
}
}
if ( CmdFlagOn(rgNetDomArgs, eCommUserNameO) ) {
Win32Err = NetDompGetUserAndPasswordForOperation(rgNetDomArgs,
eCommUserNameO,
Object,
&ObjectUser );
if ( Win32Err != ERROR_SUCCESS ) {
goto HandleTimeExit;
}
}
//
// Get the name of a domain controller
//
Win32Err = NetDompTimeGetDc( Domain,
Object,
&ObjectUser,
&Dc );
if ( Win32Err != ERROR_SUCCESS ) {
goto HandleTimeExit;
}
//
// Now, see what we are supposed to do
//
if ( CmdFlagOn(rgNetDomArgs, eCommVerify) ) {
Win32Err = NetDompVerifyTime( Domain,
Object,
&DomainUser,
&ObjectUser,
Dc,
CmdFlagOn(rgNetDomArgs, eQueryWksta),
CmdFlagOn(rgNetDomArgs, eQueryServer) );
}
if ( CmdFlagOn(rgNetDomArgs, eCommReset) ) {
Win32Err = NetDompResetTime( Domain,
Object,
&DomainUser,
&ObjectUser,
Dc,
CmdFlagOn(rgNetDomArgs, eQueryWksta),
CmdFlagOn(rgNetDomArgs, eQueryServer) );
}
HandleTimeExit:
NetApiBufferFree( Domain );
NetApiBufferFree( Dc );
NetDompFreeAuthIdent( &DomainUser );
NetDompFreeAuthIdent( &ObjectUser );
if (NO_ERROR != Win32Err)
{
NetDompDisplayErrorMessage(Win32Err);
}
return( Win32Err );
}