|
|
/*++
Copyright (c) 1987-1993 Microsoft Corporation
Module Name:
loghours.c
Abstract:
Private routines to support rotation of logon hours between local time and GMT time.
Author:
Cliff Van Dyke (cliffv) 16-Mar-93
Environment:
User mode only. Contains NT-specific code. Requires ANSI C extensions: slash-slash comments, long external names.
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windef.h>
#include <winbase.h>
#include <limits.h>
#include <math.h>
#include <lmcons.h>
#include <lmaccess.h>
#include <loghours.h>
BOOLEAN NetpRotateLogonHoursPhase1( IN BOOL ConvertToGmt, OUT PULONG RotateCount )
/*++
Routine Description:
Determine the amount to rotate the logon hours by to convert to/from GMT
Arguments:
ConvertToGmt - True to convert the logon hours from local time to GMT relative False to convert the logon hours from GMT relative to local time
RotateCount - Returns the number of bits to shift by.
Return Value:
TRUE if the RotateCount could be computed FALSE if a RotateCount could not be computed
--*/ { RTL_TIME_ZONE_INFORMATION tzi; LONG BiasInHours; NTSTATUS Status;
//
// Get the timezone data from the registry
//
Status = RtlQueryTimeZoneInformation( &tzi ); if ( !NT_SUCCESS(Status) ) { return FALSE; }
//
// Compute the amount to rotate the logon hours by
//
// Round the bias in minutes to the closest bias in hours.
// Take into consideration that Bias can be negative.
// Do this by forcing the Bias to be positive, rounding,
// then adjusting it back negative again.
//
ASSERT( tzi.Bias > -(24*60) ); BiasInHours = ((tzi.Bias + (24*60) + 30)/60) - 24;
if ( !ConvertToGmt ) { BiasInHours = - BiasInHours; }
*RotateCount = BiasInHours; return TRUE;
}
BOOLEAN NetpRotateLogonHoursPhase2( IN PBYTE LogonHours, IN DWORD UnitsPerWeek, IN LONG RotateCount )
/*++
Routine Description:
Rotate the LogonHours bit mask by the required amount.
Arguments:
LogonHours - Pointer to LogonHour bit mask
UnitsPerWeek - Number of bits in the bit mask. Must be UNITS_PER_WEEK (168).
RotateCount - Number of bits to rotate by. Must be between 31 and -31. Negative means to rotate left. Positive means to rotate right.
Return Value:
TRUE if the rotation succeeded. FALSE if a parameter was out of range
--*/ { //
// Useful constants
//
#define DWORDS_PER_WEEK ((UNITS_PER_WEEK+31)/32)
#define BYTES_PER_WEEK (UNITS_PER_WEEK/8)
DWORD AlignedLogonHours[DWORDS_PER_WEEK+1]; LONG i;
BOOLEAN RotateLeft;
//
// Ensure there are 8 bits per byte,
// 32 bits per DWORD and
// units per week is even number of bytes.
//
ASSERT( CHAR_BIT == 8 ); ASSERT( sizeof(DWORD) * CHAR_BIT == 32 ); ASSERT( UNITS_PER_WEEK/8*8 == UNITS_PER_WEEK );
//
// Validate the input parameters
//
if ( UnitsPerWeek != UNITS_PER_WEEK ) { ASSERT( UnitsPerWeek == UNITS_PER_WEEK ); return FALSE; }
if ( RotateCount == 0 ) { return TRUE; }
RotateLeft = (RotateCount < 0); RotateCount = labs( RotateCount ); if ( RotateCount > 31 ) { ASSERT ( RotateCount <= 31 ); return FALSE; }
//
// Do the left rotate.
//
if (RotateLeft) {
//
// Copy the logon hours to a DWORD aligned buffer.
//
// Duplicate the first dword at the end of the buffer to make
// the rotation code trivial.
//
RtlCopyMemory(AlignedLogonHours, LogonHours, BYTES_PER_WEEK );
RtlCopyMemory( ((PBYTE)AlignedLogonHours)+BYTES_PER_WEEK, LogonHours, sizeof(DWORD) );
//
// Actually rotate the data.
//
for ( i=0; i < DWORDS_PER_WEEK; i++ ) { AlignedLogonHours[i] = (AlignedLogonHours[i] >> RotateCount) | (AlignedLogonHours[i+1] << (32-RotateCount)); }
//
// Copy the logon hours back to the input buffer.
//
RtlCopyMemory( LogonHours, AlignedLogonHours, BYTES_PER_WEEK );
//
// Do the right rotate.
//
} else {
//
// Copy the logon hours to a DWORD aligned buffer.
//
// Duplicate the last DWORD at the front of the buffer to make
// the rotation code trivial.
//
RtlCopyMemory( &AlignedLogonHours[1], LogonHours, BYTES_PER_WEEK ); RtlCopyMemory( AlignedLogonHours, &LogonHours[BYTES_PER_WEEK-4], sizeof(DWORD));
//
// Actually rotate the data.
//
for ( i=DWORDS_PER_WEEK-1; i>=0; i-- ) { AlignedLogonHours[i+1] = (AlignedLogonHours[i+1] << RotateCount) | (AlignedLogonHours[i] >> (32-RotateCount)); }
//
// Copy the logon hours back to the input buffer.
//
RtlCopyMemory( LogonHours, &AlignedLogonHours[1], BYTES_PER_WEEK );
}
//
// Done
//
return TRUE;
}
BOOLEAN NetpRotateLogonHours( IN PBYTE LogonHours, IN DWORD UnitsPerWeek, IN BOOL ConvertToGmt )
/*++
Routine Description:
Rotate the LogonHours bit mask to/from GMT relative time.
Arguments:
LogonHours - Pointer to LogonHour bit mask
UnitsPerWeek - Number of bits in the bit mask. Must be UNITS_PER_WEEK (168).
ConvertToGmt - True to convert the logon hours from local time to GMT relative False to convert the logon hours from GMT relative to local time
Return Value:
TRUE if the rotation succeeded. FALSE if a parameter was out of range
--*/ { ULONG RotateCount;
//
// Break the functionality into two phases so that if the caller is doing
// this multiple time, he just calls Phase 1 once and Phase 2 multiple
// times.
//
if ( !NetpRotateLogonHoursPhase1( ConvertToGmt, &RotateCount ) ) { return FALSE; }
return NetpRotateLogonHoursPhase2( LogonHours, UnitsPerWeek, RotateCount );
}
|