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.
565 lines
14 KiB
565 lines
14 KiB
/*++
|
|
|
|
Copyright (c) 1987-2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
log_gmt.cpp (originally named loghours.c)
|
|
|
|
Abstract:
|
|
|
|
Private routines to support rotation of logon hours between local time
|
|
and GMT time.
|
|
|
|
Environment:
|
|
|
|
User mode only.
|
|
Contains NT-specific code.
|
|
Requires ANSI C extensions: slash-slash comments, long external names.
|
|
|
|
Revision History:
|
|
16-Mar-93 cliffv Creation.
|
|
22-Jul-97 t-danm Copied from /nt/private/nw/convert/nwconv/loghours.c
|
|
and adapted to loghours.dll.
|
|
|
|
--*/
|
|
|
|
#include "stdafx.h"
|
|
|
|
#pragma warning (disable : 4514)
|
|
#pragma warning (push,3)
|
|
|
|
#include <limits.h>
|
|
#include <math.h>
|
|
|
|
#include <lmcons.h>
|
|
#include <lmaccess.h>
|
|
#pragma warning (pop)
|
|
|
|
#include "log_gmt.h"
|
|
|
|
#include "debug.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
//#pragma hdrstop
|
|
|
|
/*++
|
|
Routine NetpRotateLogonHoursPhase1()
|
|
|
|
Determine the amount to rotate the logon hours by to convert to/from GMT
|
|
|
|
Arguments:
|
|
|
|
bConvertToGmt -
|
|
True to convert the logon hours from local time to GMT relative
|
|
False to convert the logon hours from GMT relative to local time
|
|
|
|
pRotateCount - Returns the number of bits to shift by.
|
|
Must be non NULL pointer.
|
|
|
|
Return Value:
|
|
|
|
TRUE if the pRotateCount could be computed
|
|
FALSE if a pRotateCount could not be computed
|
|
|
|
--*/
|
|
BOOLEAN
|
|
NetpRotateLogonHoursPhase1(
|
|
IN BOOL bConvertToGmt,
|
|
IN bool bAddDaylightBias,
|
|
OUT PLONG pRotateCount)
|
|
{
|
|
if ( !pRotateCount )
|
|
return FALSE;
|
|
|
|
_TRACE (1, L"Entering NetpRotateLogonHoursPhase1\n");
|
|
TIME_ZONE_INFORMATION tzi;
|
|
LONG lBiasInHours = 0;
|
|
LONG lDSTBias = 0;
|
|
const LONG HOURS_IN_DAY = 24;
|
|
|
|
//
|
|
// Get the timezone data from the registry
|
|
//
|
|
|
|
DWORD dwResult = GetTimeZoneInformation( &tzi );
|
|
if ( TIME_ZONE_ID_INVALID == dwResult )
|
|
{
|
|
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.
|
|
//
|
|
|
|
if ( bAddDaylightBias )
|
|
{
|
|
switch (dwResult)
|
|
{
|
|
case TIME_ZONE_ID_DAYLIGHT:
|
|
lDSTBias = tzi.DaylightBias;
|
|
break;
|
|
|
|
case TIME_ZONE_ID_UNKNOWN:
|
|
case TIME_ZONE_ID_STANDARD:
|
|
lDSTBias = tzi.StandardBias;
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
ASSERT( tzi.Bias > -(HOURS_IN_DAY*60) );
|
|
lBiasInHours = ((tzi.Bias + lDSTBias + (HOURS_IN_DAY*60) + 30)/60) - HOURS_IN_DAY;
|
|
|
|
|
|
if ( !bConvertToGmt )
|
|
{
|
|
lBiasInHours = - lBiasInHours;
|
|
}
|
|
|
|
/// TODO: Account for user changing the locale while the schedule grid is open
|
|
// Adjust for first day of week, if nFirstDay == 6, then no adjustment is required
|
|
// because the vector passed in starts on Sunday
|
|
int nFirstDay = GetFirstDayOfWeek ();
|
|
LONG lFirstDayShiftInHours = (bConvertToGmt ? 1 : -1);
|
|
switch (nFirstDay)
|
|
{
|
|
case 0:
|
|
lFirstDayShiftInHours *= 1 * HOURS_IN_DAY;
|
|
break;
|
|
|
|
case 1:
|
|
lFirstDayShiftInHours *= 2 * HOURS_IN_DAY;
|
|
break;
|
|
|
|
case 2:
|
|
lFirstDayShiftInHours *= 3 * HOURS_IN_DAY;
|
|
break;
|
|
|
|
case 3:
|
|
lFirstDayShiftInHours *= 4 * HOURS_IN_DAY;
|
|
break;
|
|
|
|
case 4:
|
|
lFirstDayShiftInHours *= 5 * HOURS_IN_DAY;
|
|
break;
|
|
|
|
case 5:
|
|
lFirstDayShiftInHours *= 6 * HOURS_IN_DAY;
|
|
break;
|
|
|
|
case 6:
|
|
lFirstDayShiftInHours *= 0 * HOURS_IN_DAY;
|
|
break;
|
|
|
|
default:
|
|
ASSERT (0);
|
|
break;
|
|
}
|
|
lBiasInHours += lFirstDayShiftInHours;
|
|
|
|
// NOTICE-NTRAID#NTBUG9-547513-2002/02/19-artm pRotateCount != NULL validated
|
|
// Check was added at beginning of function.
|
|
*pRotateCount = lBiasInHours;
|
|
_TRACE (-1, L"Leaving NetpRotateLogonHoursPhase1\n");
|
|
return TRUE;
|
|
} // NetpRotateLogonHoursPhase1()
|
|
|
|
|
|
|
|
/*++
|
|
Routine NetpRotateLogonHoursPhase2()
|
|
|
|
Rotate the pLogonHours bit mask by the required amount.
|
|
|
|
|
|
Arguments:
|
|
|
|
pLogonHours - Pointer to LogonHour bit mask
|
|
|
|
dwUnitsPerWeek - Number of bits in the bit mask. Must be UNITS_PER_WEEK (168).
|
|
|
|
lRotateCount - Number of bits to rotate by.
|
|
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
|
|
|
|
--*/
|
|
BOOLEAN
|
|
NetpRotateLogonHoursPhase2(
|
|
IN PBYTE pLogonHours,
|
|
IN DWORD dwUnitsPerWeek,
|
|
IN LONG lRotateCount)
|
|
{
|
|
if ( !pLogonHours )
|
|
return FALSE;
|
|
|
|
_TRACE (1, L"Entering NetpRotateLogonHoursPhase2\n");
|
|
//
|
|
// Useful constants
|
|
//
|
|
const int BYTES_PER_WEEK = (UNITS_PER_WEEK/8);
|
|
|
|
BYTE byAlignedLogonHours[BYTES_PER_WEEK*2];
|
|
::ZeroMemory (byAlignedLogonHours, BYTES_PER_WEEK*2);
|
|
LONG i = 0;
|
|
|
|
BOOLEAN bRotateLeft = FALSE;
|
|
|
|
//
|
|
// Ensure there are 8 bits per byte,
|
|
// 32 bits per DWORD and
|
|
// units per week is even number of bytes.
|
|
//
|
|
|
|
#pragma warning(disable : 4127)
|
|
ASSERT( CHAR_BIT == 8 );
|
|
ASSERT( sizeof(DWORD) * CHAR_BIT == 32 );
|
|
ASSERT( UNITS_PER_WEEK/8*8 == UNITS_PER_WEEK );
|
|
#pragma warning (default : 4127)
|
|
|
|
|
|
//
|
|
// Validate the input parameters
|
|
//
|
|
|
|
if ( dwUnitsPerWeek != UNITS_PER_WEEK )
|
|
{
|
|
#pragma warning(disable : 4127)
|
|
ASSERT( dwUnitsPerWeek == UNITS_PER_WEEK );
|
|
#pragma warning (default : 4127)
|
|
return FALSE;
|
|
}
|
|
|
|
if ( lRotateCount == 0 )
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
// NOTICE-NTRAID#NTBUG9-547513-2002/02/19-artm pLogonHours != NULL was checked
|
|
// Check was added to the beginning of the function.
|
|
|
|
bRotateLeft = (lRotateCount < 0);
|
|
lRotateCount = labs( lRotateCount );
|
|
|
|
|
|
|
|
// New algorithm: get numBytes by dividing lRotateCount/32. Shift entire array
|
|
// left or right by numBytes and then do the loop below for the remainder.
|
|
// Move bytes from the beginning to the end, or bytes from the end to the beginning
|
|
// depending on the rotation direction.
|
|
LONG lNumBYTES = lRotateCount/8;
|
|
if ( lNumBYTES > 0 )
|
|
{
|
|
RtlCopyMemory (byAlignedLogonHours, pLogonHours, BYTES_PER_WEEK);
|
|
|
|
RtlCopyMemory (((PBYTE)byAlignedLogonHours) + BYTES_PER_WEEK,
|
|
pLogonHours,
|
|
BYTES_PER_WEEK );
|
|
|
|
size_t nBytesToEnd = sizeof (byAlignedLogonHours) - lNumBYTES;
|
|
BYTE* pTemp = new BYTE[lNumBYTES];
|
|
if ( pTemp )
|
|
{
|
|
//
|
|
// Do the left rotate.
|
|
//
|
|
if ( bRotateLeft )
|
|
{
|
|
memcpy (pTemp, byAlignedLogonHours, lNumBYTES);
|
|
|
|
memmove (byAlignedLogonHours,
|
|
byAlignedLogonHours + lNumBYTES,
|
|
nBytesToEnd);
|
|
|
|
memcpy (byAlignedLogonHours + nBytesToEnd,
|
|
pTemp,
|
|
lNumBYTES);
|
|
}
|
|
else
|
|
{
|
|
// Do the right rotate
|
|
memcpy (pTemp,
|
|
byAlignedLogonHours + nBytesToEnd,
|
|
lNumBYTES);
|
|
|
|
memmove (byAlignedLogonHours + lNumBYTES,
|
|
byAlignedLogonHours,
|
|
nBytesToEnd);
|
|
|
|
memcpy (byAlignedLogonHours, pTemp, lNumBYTES);
|
|
}
|
|
delete [] pTemp;
|
|
}
|
|
|
|
lRotateCount = lRotateCount%8;
|
|
|
|
RtlCopyMemory (pLogonHours, byAlignedLogonHours, BYTES_PER_WEEK );
|
|
}
|
|
|
|
if ( lRotateCount )
|
|
{
|
|
//
|
|
// Do the left rotate.
|
|
//
|
|
if (bRotateLeft)
|
|
{
|
|
//
|
|
// Copy the logon hours to a buffer.
|
|
//
|
|
// Duplicate the entire pLogonHours buffer at the end of the
|
|
// byAlignedLogonHours buffer to make the rotation code trivial.
|
|
//
|
|
|
|
RtlCopyMemory (byAlignedLogonHours, pLogonHours, BYTES_PER_WEEK);
|
|
|
|
RtlCopyMemory (((PBYTE)byAlignedLogonHours)+BYTES_PER_WEEK,
|
|
pLogonHours,
|
|
BYTES_PER_WEEK);
|
|
|
|
//
|
|
// Actually rotate the data.
|
|
//
|
|
|
|
for ( i=0; i < BYTES_PER_WEEK; i++ )
|
|
{
|
|
byAlignedLogonHours[i] =
|
|
(byAlignedLogonHours[i] >> (BYTE) lRotateCount) |
|
|
(byAlignedLogonHours[i+1] << (BYTE) (8-lRotateCount));
|
|
}
|
|
|
|
//
|
|
// Copy the logon hours back to the input buffer.
|
|
//
|
|
|
|
RtlCopyMemory (pLogonHours, byAlignedLogonHours, BYTES_PER_WEEK);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Do the right rotate.
|
|
//
|
|
//
|
|
// 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 (&byAlignedLogonHours[1], pLogonHours, BYTES_PER_WEEK);
|
|
RtlCopyMemory (byAlignedLogonHours,
|
|
&pLogonHours[BYTES_PER_WEEK-1],
|
|
sizeof(BYTE));
|
|
|
|
//
|
|
// Actually rotate the data.
|
|
//
|
|
|
|
for (i = BYTES_PER_WEEK - 1; i >= 0; i-- )
|
|
{
|
|
byAlignedLogonHours[i+1] =
|
|
(byAlignedLogonHours[i+1] << (BYTE) lRotateCount) |
|
|
(byAlignedLogonHours[i] >> (BYTE) (8-lRotateCount));
|
|
}
|
|
|
|
//
|
|
// Copy the logon hours back to the input buffer.
|
|
//
|
|
|
|
RtlCopyMemory (pLogonHours, &byAlignedLogonHours[1], BYTES_PER_WEEK);
|
|
|
|
}
|
|
}
|
|
_TRACE (-1, L"Leaving NetpRotateLogonHoursPhase2\n");
|
|
return TRUE;
|
|
|
|
} // NetpRotateLogonHoursPhase2()
|
|
|
|
|
|
/*++
|
|
Routine NetpRotateLogonHours()
|
|
|
|
Rotate the pLogonHours bit mask to/from GMT relative time.
|
|
|
|
|
|
Arguments:
|
|
|
|
pLogonHours - Pointer to LogonHour bit mask
|
|
|
|
dwUnitsPerWeek - Number of bits in the bit mask. Must be UNITS_PER_WEEK (168).
|
|
|
|
bConvertToGmt -
|
|
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
|
|
|
|
--*/
|
|
BOOLEAN
|
|
NetpRotateLogonHours(
|
|
IN OUT PBYTE rgbLogonHours, // Array of 21 bytes
|
|
IN DWORD cbitUnitsPerWeek, // Must be 21 * 8 = 168
|
|
IN BOOL fConvertToGmt,
|
|
IN bool bAddDaylightBias)
|
|
{
|
|
if ( !rgbLogonHours )
|
|
return FALSE;
|
|
|
|
LONG lRotateCount = 0;
|
|
|
|
//
|
|
// 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 (fConvertToGmt, bAddDaylightBias, &lRotateCount) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return NetpRotateLogonHoursPhase2 (rgbLogonHours, cbitUnitsPerWeek, lRotateCount );
|
|
} // NetpRotateLogonHours()
|
|
|
|
|
|
/*++
|
|
Routine NetpRotateLogonHoursBYTE()
|
|
|
|
Rotate the pLogonHours BYTE array to/from GMT relative time.
|
|
Each BYTE is one hour. The contents of a BYTE must not change
|
|
|
|
|
|
Arguments:
|
|
|
|
pLogonHours - Pointer to LogonHour bit mask
|
|
|
|
dwUnitsPerWeek - Number of BYTES in the BYTE array. Must be UNITS_PER_WEEK (168).
|
|
|
|
bConvertToGmt -
|
|
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
|
|
|
|
--*/
|
|
BOOLEAN
|
|
NetpRotateLogonHoursBYTE(
|
|
IN OUT PBYTE rgbLogonHours, // Array of 168 bytes
|
|
IN DWORD cbitUnitsPerWeek, // Must be 21 * 8 = 168
|
|
IN BOOL fConvertToGmt,
|
|
IN bool bAddDaylightBias)
|
|
{
|
|
if ( !rgbLogonHours )
|
|
return FALSE;
|
|
|
|
LONG lRotateCount = 0;
|
|
|
|
//
|
|
// 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 (fConvertToGmt, bAddDaylightBias, &lRotateCount) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
// NOTICE-NTRAID#NTBUG9-547513-2002/02/19-artm Validate rgbLogonHours
|
|
// Check correctly done at beginning of function.
|
|
|
|
// FUTURE-2002/04/05-artm cbitUnitsPerWeek should be validated
|
|
// rgbLogonHours should not be NULL and cbitUnitsPerWeek should equal UNITS_PER_WEEK
|
|
BOOLEAN bResult = TRUE;
|
|
|
|
if ( lRotateCount != 0 )
|
|
{
|
|
size_t numBytes = abs (lRotateCount);
|
|
PBYTE pTemp = new BYTE[cbitUnitsPerWeek + numBytes];
|
|
if ( pTemp )
|
|
{
|
|
if ( lRotateCount < 0 ) // shift left
|
|
{
|
|
// Copy the entire array and then start over with numBytes BYTES from
|
|
// the start of the array to fill up to the end of the temp array.
|
|
// Then shift over numBytes BYTES and copy 168 bytes from the temp
|
|
// array back to the original array.
|
|
memcpy (pTemp, rgbLogonHours, cbitUnitsPerWeek);
|
|
memcpy (pTemp + cbitUnitsPerWeek, rgbLogonHours, numBytes);
|
|
memcpy (rgbLogonHours, pTemp + numBytes, cbitUnitsPerWeek);
|
|
}
|
|
else // lRotateCount > 0 -- shift right
|
|
{
|
|
// Copy numBytes BYTES from the end of the array and then copy
|
|
// the entire array to fill up to the end of the temp array.
|
|
// The copy 168 bytes from the beginning of the temp array back
|
|
// to the original array.
|
|
memcpy (pTemp, rgbLogonHours + (cbitUnitsPerWeek - numBytes), numBytes);
|
|
memcpy (pTemp + numBytes, rgbLogonHours, cbitUnitsPerWeek);
|
|
memcpy (rgbLogonHours, pTemp, cbitUnitsPerWeek);
|
|
}
|
|
|
|
delete [] pTemp;
|
|
}
|
|
else
|
|
bResult = FALSE;
|
|
}
|
|
|
|
return bResult;
|
|
} // NetpRotateLogonHours()
|
|
|
|
|
|
//****************************************************************************
|
|
//
|
|
// GetFirstDayOfWeek
|
|
//
|
|
// Use the locale API to get the "official" first day of the week.
|
|
//
|
|
//****************************************************************************
|
|
int GetFirstDayOfWeek()
|
|
{
|
|
_TRACE (1, L"Entering GetFirstDayOfWeek\n");
|
|
int nFirstDay = -1;
|
|
WCHAR szBuf[10];
|
|
|
|
int nRet = ::GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_IFIRSTDAYOFWEEK,
|
|
szBuf, sizeof(szBuf)/sizeof(WCHAR));
|
|
if ( nRet > 0 )
|
|
{
|
|
int nDay = ::_wtoi( szBuf );
|
|
if ( nDay < 0 || nDay > 6 )
|
|
{
|
|
_TRACE (0, L"Out of range, IFIRSTDAYOFWEEK = %d\n", nDay);
|
|
}
|
|
else
|
|
nFirstDay = nDay;
|
|
}
|
|
else
|
|
{
|
|
_TRACE (0, L"GetLocaleInfo(IFIRSTDAYOFWEEK) failed - %d\n", GetLastError ());
|
|
}
|
|
|
|
_TRACE (-1, L"Leaving GetFirstDayOfWeek: first day = %d\n", nFirstDay);
|
|
return nFirstDay;
|
|
}
|