Source code of Windows XP (NT5)
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.

310 lines
6.2 KiB

  1. /*++
  2. Copyright (c) 1987-1993 Microsoft Corporation
  3. Module Name:
  4. loghours.c
  5. Abstract:
  6. Private routines to support rotation of logon hours between local time
  7. and GMT time.
  8. Author:
  9. Cliff Van Dyke (cliffv) 16-Mar-93
  10. Environment:
  11. User mode only.
  12. Contains NT-specific code.
  13. Requires ANSI C extensions: slash-slash comments, long external names.
  14. Revision History:
  15. --*/
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #include <windef.h>
  20. #include <winbase.h>
  21. #include <limits.h>
  22. #include <math.h>
  23. #include <lmcons.h>
  24. #include <lmaccess.h>
  25. #include <loghours.h>
  26. BOOLEAN
  27. NetpRotateLogonHoursPhase1(
  28. IN BOOL ConvertToGmt,
  29. OUT PULONG RotateCount
  30. )
  31. /*++
  32. Routine Description:
  33. Determine the amount to rotate the logon hours by to convert to/from GMT
  34. Arguments:
  35. ConvertToGmt -
  36. True to convert the logon hours from local time to GMT relative
  37. False to convert the logon hours from GMT relative to local time
  38. RotateCount - Returns the number of bits to shift by.
  39. Return Value:
  40. TRUE if the RotateCount could be computed
  41. FALSE if a RotateCount could not be computed
  42. --*/
  43. {
  44. RTL_TIME_ZONE_INFORMATION tzi;
  45. LONG BiasInHours;
  46. NTSTATUS Status;
  47. //
  48. // Get the timezone data from the registry
  49. //
  50. Status = RtlQueryTimeZoneInformation( &tzi );
  51. if ( !NT_SUCCESS(Status) ) {
  52. return FALSE;
  53. }
  54. //
  55. // Compute the amount to rotate the logon hours by
  56. //
  57. // Round the bias in minutes to the closest bias in hours.
  58. // Take into consideration that Bias can be negative.
  59. // Do this by forcing the Bias to be positive, rounding,
  60. // then adjusting it back negative again.
  61. //
  62. ASSERT( tzi.Bias > -(24*60) );
  63. BiasInHours = ((tzi.Bias + (24*60) + 30)/60) - 24;
  64. if ( !ConvertToGmt ) {
  65. BiasInHours = - BiasInHours;
  66. }
  67. *RotateCount = BiasInHours;
  68. return TRUE;
  69. }
  70. BOOLEAN
  71. NetpRotateLogonHoursPhase2(
  72. IN PBYTE LogonHours,
  73. IN DWORD UnitsPerWeek,
  74. IN LONG RotateCount
  75. )
  76. /*++
  77. Routine Description:
  78. Rotate the LogonHours bit mask by the required amount.
  79. Arguments:
  80. LogonHours - Pointer to LogonHour bit mask
  81. UnitsPerWeek - Number of bits in the bit mask. Must be UNITS_PER_WEEK (168).
  82. RotateCount - Number of bits to rotate by. Must be between 31 and -31.
  83. Negative means to rotate left.
  84. Positive means to rotate right.
  85. Return Value:
  86. TRUE if the rotation succeeded.
  87. FALSE if a parameter was out of range
  88. --*/
  89. {
  90. //
  91. // Useful constants
  92. //
  93. #define DWORDS_PER_WEEK ((UNITS_PER_WEEK+31)/32)
  94. #define BYTES_PER_WEEK (UNITS_PER_WEEK/8)
  95. DWORD AlignedLogonHours[DWORDS_PER_WEEK+1];
  96. LONG i;
  97. BOOLEAN RotateLeft;
  98. //
  99. // Ensure there are 8 bits per byte,
  100. // 32 bits per DWORD and
  101. // units per week is even number of bytes.
  102. //
  103. ASSERT( CHAR_BIT == 8 );
  104. ASSERT( sizeof(DWORD) * CHAR_BIT == 32 );
  105. ASSERT( UNITS_PER_WEEK/8*8 == UNITS_PER_WEEK );
  106. //
  107. // Validate the input parameters
  108. //
  109. if ( UnitsPerWeek != UNITS_PER_WEEK ) {
  110. ASSERT( UnitsPerWeek == UNITS_PER_WEEK );
  111. return FALSE;
  112. }
  113. if ( RotateCount == 0 ) {
  114. return TRUE;
  115. }
  116. RotateLeft = (RotateCount < 0);
  117. RotateCount = labs( RotateCount );
  118. if ( RotateCount > 31 ) {
  119. ASSERT ( RotateCount <= 31 );
  120. return FALSE;
  121. }
  122. //
  123. // Do the left rotate.
  124. //
  125. if (RotateLeft) {
  126. //
  127. // Copy the logon hours to a DWORD aligned buffer.
  128. //
  129. // Duplicate the first dword at the end of the buffer to make
  130. // the rotation code trivial.
  131. //
  132. RtlCopyMemory(AlignedLogonHours, LogonHours, BYTES_PER_WEEK );
  133. RtlCopyMemory( ((PBYTE)AlignedLogonHours)+BYTES_PER_WEEK,
  134. LogonHours,
  135. sizeof(DWORD) );
  136. //
  137. // Actually rotate the data.
  138. //
  139. for ( i=0; i < DWORDS_PER_WEEK; i++ ) {
  140. AlignedLogonHours[i] =
  141. (AlignedLogonHours[i] >> RotateCount) |
  142. (AlignedLogonHours[i+1] << (32-RotateCount));
  143. }
  144. //
  145. // Copy the logon hours back to the input buffer.
  146. //
  147. RtlCopyMemory( LogonHours, AlignedLogonHours, BYTES_PER_WEEK );
  148. //
  149. // Do the right rotate.
  150. //
  151. } else {
  152. //
  153. // Copy the logon hours to a DWORD aligned buffer.
  154. //
  155. // Duplicate the last DWORD at the front of the buffer to make
  156. // the rotation code trivial.
  157. //
  158. RtlCopyMemory( &AlignedLogonHours[1], LogonHours, BYTES_PER_WEEK );
  159. RtlCopyMemory( AlignedLogonHours,
  160. &LogonHours[BYTES_PER_WEEK-4],
  161. sizeof(DWORD));
  162. //
  163. // Actually rotate the data.
  164. //
  165. for ( i=DWORDS_PER_WEEK-1; i>=0; i-- ) {
  166. AlignedLogonHours[i+1] =
  167. (AlignedLogonHours[i+1] << RotateCount) |
  168. (AlignedLogonHours[i] >> (32-RotateCount));
  169. }
  170. //
  171. // Copy the logon hours back to the input buffer.
  172. //
  173. RtlCopyMemory( LogonHours, &AlignedLogonHours[1], BYTES_PER_WEEK );
  174. }
  175. //
  176. // Done
  177. //
  178. return TRUE;
  179. }
  180. BOOLEAN
  181. NetpRotateLogonHours(
  182. IN PBYTE LogonHours,
  183. IN DWORD UnitsPerWeek,
  184. IN BOOL ConvertToGmt
  185. )
  186. /*++
  187. Routine Description:
  188. Rotate the LogonHours bit mask to/from GMT relative time.
  189. Arguments:
  190. LogonHours - Pointer to LogonHour bit mask
  191. UnitsPerWeek - Number of bits in the bit mask. Must be UNITS_PER_WEEK (168).
  192. ConvertToGmt -
  193. True to convert the logon hours from local time to GMT relative
  194. False to convert the logon hours from GMT relative to local time
  195. Return Value:
  196. TRUE if the rotation succeeded.
  197. FALSE if a parameter was out of range
  198. --*/
  199. {
  200. ULONG RotateCount;
  201. //
  202. // Break the functionality into two phases so that if the caller is doing
  203. // this multiple time, he just calls Phase 1 once and Phase 2 multiple
  204. // times.
  205. //
  206. if ( !NetpRotateLogonHoursPhase1( ConvertToGmt, &RotateCount ) ) {
  207. return FALSE;
  208. }
  209. return NetpRotateLogonHoursPhase2( LogonHours, UnitsPerWeek, RotateCount );
  210. }