|
|
/*++
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 ); }
|