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.

416 lines
9.4 KiB

  1. /*++
  2. Copyright (c) 1987-2001 Microsoft Corporation
  3. Module Name:
  4. log_gmt.cpp (originally named loghours.c)
  5. Abstract:
  6. Private routines to support rotation of logon hours between local time
  7. and GMT time.
  8. Environment:
  9. User mode only.
  10. Contains NT-specific code.
  11. Requires ANSI C extensions: slash-slash comments, long external names.
  12. Revision History:
  13. 16-Mar-93 cliffv Creation.
  14. 22-Jul-97 t-danm Copied from /nt/private/nw/convert/nwconv/loghours.c
  15. and adapted to loghours.dll.
  16. --*/
  17. //#include "stdafx.h"
  18. #pragma warning (disable : 4514)
  19. #pragma warning (push,3)
  20. extern "C" {
  21. #include <nt.h>
  22. #include <ntrtl.h>
  23. #include <nturtl.h>
  24. #include <windef.h>
  25. #include <winbase.h>
  26. }
  27. #include <limits.h>
  28. #include <math.h>
  29. #include <lmcons.h>
  30. #include <lmaccess.h>
  31. #pragma warning (pop)
  32. #include "log_gmt.h"
  33. //#pragma hdrstop
  34. /*++
  35. Routine NetpRotateLogonHoursPhase1()
  36. Determine the amount to rotate the logon hours by to convert to/from GMT
  37. Arguments:
  38. ConvertToGmt -
  39. True to convert the logon hours from local time to GMT relative
  40. False to convert the logon hours from GMT relative to local time
  41. RotateCount - Returns the number of bits to shift by.
  42. Return Value:
  43. TRUE if the RotateCount could be computed
  44. FALSE if a RotateCount could not be computed
  45. --*/
  46. BOOLEAN
  47. NetpRotateLogonHoursPhase1(
  48. IN BOOL ConvertToGmt,
  49. IN bool bAddDaylightBias,
  50. OUT PLONG RotateCount)
  51. {
  52. TIME_ZONE_INFORMATION tzi;
  53. LONG BiasInHours = 0;
  54. LONG DSTBias = 0;
  55. //
  56. // Get the timezone data from the registry
  57. //
  58. DWORD dwResult = GetTimeZoneInformation( &tzi );
  59. if ( TIME_ZONE_ID_INVALID == dwResult )
  60. {
  61. return FALSE;
  62. }
  63. //
  64. // Compute the amount to rotate the logon hours by
  65. //
  66. // Round the bias in minutes to the closest bias in hours.
  67. // Take into consideration that Bias can be negative.
  68. // Do this by forcing the Bias to be positive, rounding,
  69. // then adjusting it back negative again.
  70. //
  71. if ( bAddDaylightBias )
  72. {
  73. switch (dwResult)
  74. {
  75. case TIME_ZONE_ID_DAYLIGHT:
  76. DSTBias = tzi.DaylightBias;
  77. break;
  78. case TIME_ZONE_ID_UNKNOWN:
  79. case TIME_ZONE_ID_STANDARD:
  80. DSTBias = tzi.StandardBias;
  81. break;
  82. default:
  83. return FALSE;
  84. }
  85. }
  86. ASSERT( tzi.Bias > -(24*60) );
  87. BiasInHours = ((tzi.Bias + DSTBias + (24*60) + 30)/60) - 24;
  88. if ( !ConvertToGmt )
  89. {
  90. BiasInHours = - BiasInHours;
  91. }
  92. *RotateCount = BiasInHours;
  93. return TRUE;
  94. } // NetpRotateLogonHoursPhase1()
  95. /*++
  96. Routine NetpRotateLogonHoursPhase2()
  97. Rotate the LogonHours bit mask by the required amount.
  98. Arguments:
  99. LogonHours - Pointer to LogonHour bit mask
  100. UnitsPerWeek - Number of bits in the bit mask. Must be UNITS_PER_WEEK (168).
  101. RotateCount - Number of bits to rotate by. Must be between 31 and -31.
  102. Negative means to rotate left.
  103. Positive means to rotate right.
  104. Return Value:
  105. TRUE if the rotation succeeded.
  106. FALSE if a parameter was out of range
  107. --*/
  108. BOOLEAN
  109. NetpRotateLogonHoursPhase2(
  110. IN PBYTE LogonHours,
  111. IN DWORD UnitsPerWeek,
  112. IN LONG RotateCount)
  113. {
  114. //
  115. // Useful constants
  116. //
  117. const int DWORDS_PER_WEEK = ((UNITS_PER_WEEK+31)/32);
  118. const int BYTES_PER_WEEK = (UNITS_PER_WEEK/8);
  119. DWORD AlignedLogonHours[DWORDS_PER_WEEK+1];
  120. ::ZeroMemory (AlignedLogonHours, sizeof (DWORD) * (DWORDS_PER_WEEK+1));
  121. LONG i = 0;
  122. BOOLEAN RotateLeft = FALSE;
  123. //
  124. // Ensure there are 8 bits per byte,
  125. // 32 bits per DWORD and
  126. // units per week is even number of bytes.
  127. //
  128. #pragma warning(disable : 4127)
  129. ASSERT( CHAR_BIT == 8 );
  130. ASSERT( sizeof(DWORD) * CHAR_BIT == 32 );
  131. ASSERT( UNITS_PER_WEEK/8*8 == UNITS_PER_WEEK );
  132. #pragma warning (default : 4127)
  133. //
  134. // Validate the input parameters
  135. //
  136. if ( UnitsPerWeek != UNITS_PER_WEEK )
  137. {
  138. ASSERT( UnitsPerWeek == UNITS_PER_WEEK );
  139. return FALSE;
  140. }
  141. if ( RotateCount == 0 )
  142. {
  143. return TRUE;
  144. }
  145. RotateLeft = (RotateCount < 0);
  146. RotateCount = labs( RotateCount );
  147. if ( RotateCount > 31 )
  148. {
  149. ASSERT ( RotateCount <= 31 );
  150. return FALSE;
  151. }
  152. //
  153. // Do the left rotate.
  154. //
  155. if (RotateLeft)
  156. {
  157. //
  158. // Copy the logon hours to a DWORD aligned buffer.
  159. //
  160. // Duplicate the first dword at the end of the buffer to make
  161. // the rotation code trivial.
  162. //
  163. RtlCopyMemory(AlignedLogonHours, LogonHours, BYTES_PER_WEEK );
  164. RtlCopyMemory( ((PBYTE)AlignedLogonHours)+BYTES_PER_WEEK,
  165. LogonHours,
  166. sizeof(DWORD) );
  167. //
  168. // Actually rotate the data.
  169. //
  170. for ( i=0; i < DWORDS_PER_WEEK; i++ )
  171. {
  172. AlignedLogonHours[i] =
  173. (AlignedLogonHours[i] >> RotateCount) |
  174. (AlignedLogonHours[i+1] << (32-RotateCount));
  175. }
  176. //
  177. // Copy the logon hours back to the input buffer.
  178. //
  179. RtlCopyMemory( LogonHours, AlignedLogonHours, BYTES_PER_WEEK );
  180. //
  181. // Do the right rotate.
  182. //
  183. }
  184. else
  185. {
  186. //
  187. // Copy the logon hours to a DWORD aligned buffer.
  188. //
  189. // Duplicate the last DWORD at the front of the buffer to make
  190. // the rotation code trivial.
  191. //
  192. RtlCopyMemory( &AlignedLogonHours[1], LogonHours, BYTES_PER_WEEK );
  193. RtlCopyMemory( AlignedLogonHours,
  194. &LogonHours[BYTES_PER_WEEK-4],
  195. sizeof(DWORD));
  196. //
  197. // Actually rotate the data.
  198. //
  199. for ( i=DWORDS_PER_WEEK-1; i>=0; i-- )
  200. {
  201. AlignedLogonHours[i+1] =
  202. (AlignedLogonHours[i+1] << RotateCount) |
  203. (AlignedLogonHours[i] >> (32-RotateCount));
  204. }
  205. //
  206. // Copy the logon hours back to the input buffer.
  207. //
  208. RtlCopyMemory( LogonHours, &AlignedLogonHours[1], BYTES_PER_WEEK );
  209. }
  210. return TRUE;
  211. } // NetpRotateLogonHoursPhase2()
  212. /*++
  213. Routine NetpRotateLogonHours()
  214. Rotate the LogonHours bit mask to/from GMT relative time.
  215. Arguments:
  216. LogonHours - Pointer to LogonHour bit mask
  217. UnitsPerWeek - Number of bits in the bit mask. Must be UNITS_PER_WEEK (168).
  218. ConvertToGmt -
  219. True to convert the logon hours from local time to GMT relative
  220. False to convert the logon hours from GMT relative to local time
  221. Return Value:
  222. TRUE if the rotation succeeded.
  223. FALSE if a parameter was out of range
  224. --*/
  225. BOOLEAN
  226. NetpRotateLogonHours(
  227. IN OUT PBYTE rgbLogonHours, // Array of 21 bytes
  228. IN DWORD cbitUnitsPerWeek, // Must be 21 * 8 = 168
  229. IN BOOL fConvertToGmt,
  230. IN bool bAddDaylightBias)
  231. {
  232. LONG RotateCount = 0;
  233. //
  234. // Break the functionality into two phases so that if the caller is doing
  235. // this multiple time, he just calls Phase 1 once and Phase 2 multiple
  236. // times.
  237. //
  238. if ( !NetpRotateLogonHoursPhase1 (fConvertToGmt, bAddDaylightBias, &RotateCount) )
  239. {
  240. return FALSE;
  241. }
  242. return NetpRotateLogonHoursPhase2 (rgbLogonHours, cbitUnitsPerWeek, RotateCount );
  243. } // NetpRotateLogonHours()
  244. /*++
  245. Routine NetpRotateLogonHoursBYTE()
  246. Rotate the LogonHours BYTE array to/from GMT relative time.
  247. Each BYTE is one hour. The contents of a BYTE must not change
  248. Arguments:
  249. LogonHours - Pointer to LogonHour bit mask
  250. UnitsPerWeek - Number of BYTES in the BYTE array. Must be UNITS_PER_WEEK (168).
  251. ConvertToGmt -
  252. True to convert the logon hours from local time to GMT relative
  253. False to convert the logon hours from GMT relative to local time
  254. Return Value:
  255. TRUE if the rotation succeeded.
  256. FALSE if a parameter was out of range
  257. --*/
  258. BOOLEAN
  259. NetpRotateLogonHoursBYTE(
  260. IN OUT PBYTE rgbLogonHours, // Array of 168 bytes
  261. IN DWORD cbitUnitsPerWeek, // Must be 21 * 8 = 168
  262. IN BOOL fConvertToGmt,
  263. IN bool bAddDaylightBias)
  264. {
  265. LONG RotateCount = 0;
  266. //
  267. // Break the functionality into two phases so that if the caller is doing
  268. // this multiple time, he just calls Phase 1 once and Phase 2 multiple
  269. // times.
  270. //
  271. if ( !NetpRotateLogonHoursPhase1 (fConvertToGmt, bAddDaylightBias, &RotateCount) )
  272. {
  273. return FALSE;
  274. }
  275. BOOLEAN bResult = TRUE;
  276. ASSERT (RotateCount >= -12 && RotateCount <= 12);
  277. if ( RotateCount != 0 )
  278. {
  279. size_t numBytes = abs (RotateCount);
  280. PBYTE pTemp = new BYTE[cbitUnitsPerWeek + numBytes];
  281. if ( pTemp )
  282. {
  283. if ( RotateCount < 0 ) // shift left
  284. {
  285. // Copy the entire array and then start over with numBytes BYTES from
  286. // the start of the array to fill up to the end of the temp array.
  287. // Then shift over numBytes BYTES and copy 168 bytes from the temp
  288. // array back to the original array.
  289. memcpy (pTemp, rgbLogonHours, cbitUnitsPerWeek);
  290. memcpy (pTemp + cbitUnitsPerWeek, rgbLogonHours, numBytes);
  291. memcpy (rgbLogonHours, pTemp + numBytes, cbitUnitsPerWeek);
  292. }
  293. else // RotateCount > 0 -- shift right
  294. {
  295. // Copy numBytes BYTES from the end of the array and then copy
  296. // the entire array to fill up to the end of the temp array.
  297. // The copy 168 bytes from the beginning of the temp array back
  298. // to the original array.
  299. memcpy (pTemp, rgbLogonHours + (cbitUnitsPerWeek - numBytes), numBytes);
  300. memcpy (pTemp + numBytes, rgbLogonHours, cbitUnitsPerWeek);
  301. memcpy (rgbLogonHours, pTemp, cbitUnitsPerWeek);
  302. }
  303. delete [] pTemp;
  304. }
  305. else
  306. bResult = FALSE;
  307. }
  308. return bResult;
  309. } // NetpRotateLogonHours()