Leaked source code of windows server 2003
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.

1979 lines
61 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. datetime.c
  5. Abstract:
  6. This module implements Win32 time of day functions
  7. Author:
  8. Mark Lucovsky (markl) 08-Oct-1990
  9. Revision History:
  10. --*/
  11. #include "basedll.h"
  12. #define IsActiveConsoleSession() (USER_SHARED_DATA->ActiveConsoleId == NtCurrentPeb()->SessionId)
  13. ULONG
  14. CalcClientTimeZoneIdAndBias(
  15. IN CONST TIME_ZONE_INFORMATION *ptzi,
  16. OUT KSYSTEM_TIME *pBias);
  17. BOOL IsTimeZoneRedirectionEnabled();
  18. VOID
  19. WINAPI
  20. GetLocalTime(
  21. LPSYSTEMTIME lpLocalTime
  22. )
  23. /*++
  24. Routine Description:
  25. The current local system date and time can be returned using
  26. GetLocalTime.
  27. Arguments:
  28. lpLocalTime - Returns the current system date and time:
  29. SYSTEMTIME Structure:
  30. WORD wYear - Returns the current year.
  31. WORD wMonth - Returns the current month with January equal to 1.
  32. WORD wDayOfWeek - Returns the current day of the week where
  33. 0=Sunday, 1=Monday...
  34. WORD wDay - Returns the current day of the month.
  35. WORD wHour - Returns the current hour.
  36. WORD wMinute - Returns the current minute within the hour.
  37. WORD wSecond - Returns the current second within the minute.
  38. WORD wMilliseconds - Returns the current millisecond within the
  39. second.
  40. Return Value:
  41. None.
  42. --*/
  43. {
  44. LARGE_INTEGER LocalTime;
  45. LARGE_INTEGER SystemTime;
  46. LARGE_INTEGER Bias;
  47. TIME_FIELDS TimeFields;
  48. volatile KSYSTEM_TIME *pRealBias;
  49. if(IsTimeZoneRedirectionEnabled()) {
  50. pRealBias=&(BaseStaticServerData->ktTermsrvClientBias);
  51. } else {
  52. pRealBias=&(USER_SHARED_DATA->TimeZoneBias);
  53. }
  54. //
  55. // Read system time from shared region.
  56. //
  57. do {
  58. SystemTime.HighPart = USER_SHARED_DATA->SystemTime.High1Time;
  59. SystemTime.LowPart = USER_SHARED_DATA->SystemTime.LowPart;
  60. } while (SystemTime.HighPart != USER_SHARED_DATA->SystemTime.High2Time);
  61. //
  62. // Read time zone bias from shared region.
  63. // If it's terminal server session use client bias.
  64. do {
  65. Bias.HighPart = pRealBias->High1Time;
  66. Bias.LowPart = pRealBias->LowPart;
  67. } while (Bias.HighPart != pRealBias->High2Time);
  68. LocalTime.QuadPart = SystemTime.QuadPart - Bias.QuadPart;
  69. RtlTimeToTimeFields(&LocalTime,&TimeFields);
  70. lpLocalTime->wYear = TimeFields.Year ;
  71. lpLocalTime->wMonth = TimeFields.Month ;
  72. lpLocalTime->wDayOfWeek = TimeFields.Weekday ;
  73. lpLocalTime->wDay = TimeFields.Day ;
  74. lpLocalTime->wHour = TimeFields.Hour ;
  75. lpLocalTime->wMinute = TimeFields.Minute ;
  76. lpLocalTime->wSecond = TimeFields.Second ;
  77. lpLocalTime->wMilliseconds = TimeFields.Milliseconds;
  78. }
  79. VOID
  80. WINAPI
  81. GetSystemTime(
  82. LPSYSTEMTIME lpSystemTime
  83. )
  84. /*++
  85. Routine Description:
  86. The current system date and time (UTC based) can be returned using
  87. GetSystemTime.
  88. Arguments:
  89. lpSystemTime - Returns the current system date and time:
  90. SYSTEMTIME Structure:
  91. WORD wYear - Returns the current year.
  92. WORD wMonth - Returns the current month with January equal to 1.
  93. WORD wDayOfWeek - Returns the current day of the week where
  94. 0=Sunday, 1=Monday...
  95. WORD wDay - Returns the current day of the month.
  96. WORD wHour - Returns the current hour.
  97. WORD wMinute - Returns the current minute within the hour.
  98. WORD wSecond - Returns the current second within the minute.
  99. WORD wMilliseconds - Returns the current millisecond within the
  100. second.
  101. Return Value:
  102. None.
  103. --*/
  104. {
  105. LARGE_INTEGER SystemTime;
  106. TIME_FIELDS TimeFields;
  107. //
  108. // Read system time from shared region.
  109. //
  110. do {
  111. SystemTime.HighPart = USER_SHARED_DATA->SystemTime.High1Time;
  112. SystemTime.LowPart = USER_SHARED_DATA->SystemTime.LowPart;
  113. } while (SystemTime.HighPart != USER_SHARED_DATA->SystemTime.High2Time);
  114. RtlTimeToTimeFields(&SystemTime,&TimeFields);
  115. lpSystemTime->wYear = TimeFields.Year ;
  116. lpSystemTime->wMonth = TimeFields.Month ;
  117. lpSystemTime->wDayOfWeek = TimeFields.Weekday ;
  118. lpSystemTime->wDay = TimeFields.Day ;
  119. lpSystemTime->wHour = TimeFields.Hour ;
  120. lpSystemTime->wMinute = TimeFields.Minute ;
  121. lpSystemTime->wSecond = TimeFields.Second ;
  122. lpSystemTime->wMilliseconds = TimeFields.Milliseconds;
  123. }
  124. VOID
  125. WINAPI
  126. GetSystemTimeAsFileTime(
  127. LPFILETIME lpSystemTimeAsFileTime
  128. )
  129. /*++
  130. Routine Description:
  131. The current system date and time (UTC based) can be returned using
  132. GetSystemTimeAsFileTime.
  133. Arguments:
  134. lpSystemTimeAsFileTime - Returns the current system date and time formatted as
  135. a FILETIME structure
  136. Return Value:
  137. None.
  138. --*/
  139. {
  140. LARGE_INTEGER SystemTime;
  141. //
  142. // Read system time from shared region.
  143. //
  144. do {
  145. SystemTime.HighPart = USER_SHARED_DATA->SystemTime.High1Time;
  146. SystemTime.LowPart = USER_SHARED_DATA->SystemTime.LowPart;
  147. } while (SystemTime.HighPart != USER_SHARED_DATA->SystemTime.High2Time);
  148. lpSystemTimeAsFileTime->dwLowDateTime = SystemTime.LowPart;
  149. lpSystemTimeAsFileTime->dwHighDateTime = SystemTime.HighPart;
  150. }
  151. BOOL
  152. WINAPI
  153. SetSystemTime(
  154. CONST SYSTEMTIME *lpSystemTime
  155. )
  156. /*++
  157. Routine Description:
  158. The current UTC based system date and time can be set using
  159. SetSystemTime.
  160. Arguments:
  161. lpSystemTime - Supplies the date and time to set. The wDayOfWeek field
  162. is ignored.
  163. Return Value:
  164. TRUE - The current system date and time was set.
  165. FALSE/NULL - The operation failed. Extended error status is available
  166. using GetLastError.
  167. --*/
  168. {
  169. LARGE_INTEGER SystemTime;
  170. TIME_FIELDS TimeFields;
  171. BOOLEAN ReturnValue;
  172. PVOID State;
  173. NTSTATUS Status;
  174. ReturnValue = TRUE;
  175. TimeFields.Year = lpSystemTime->wYear ;
  176. TimeFields.Month = lpSystemTime->wMonth ;
  177. TimeFields.Day = lpSystemTime->wDay ;
  178. TimeFields.Hour = lpSystemTime->wHour ;
  179. TimeFields.Minute = lpSystemTime->wMinute ;
  180. TimeFields.Second = lpSystemTime->wSecond ;
  181. TimeFields.Milliseconds = lpSystemTime->wMilliseconds;
  182. if ( !RtlTimeFieldsToTime(&TimeFields,&SystemTime) ) {
  183. Status = STATUS_INVALID_PARAMETER;
  184. ReturnValue = FALSE;
  185. }
  186. else {
  187. Status = BasepAcquirePrivilegeEx( SE_SYSTEMTIME_PRIVILEGE, &State );
  188. if ( NT_SUCCESS(Status) ) {
  189. Status = NtSetSystemTime(&SystemTime,NULL);
  190. BasepReleasePrivilege( State );
  191. }
  192. if ( !NT_SUCCESS(Status) ) {
  193. ReturnValue = FALSE;
  194. }
  195. }
  196. if ( !ReturnValue ) {
  197. BaseSetLastNTError(Status);
  198. }
  199. return ReturnValue;
  200. }
  201. BOOL
  202. WINAPI
  203. SetLocalTime(
  204. CONST SYSTEMTIME *lpLocalTime
  205. )
  206. /*++
  207. Routine Description:
  208. The current local system date and time can be set using
  209. SetLocalTime.
  210. Arguments:
  211. lpSystemTime - Supplies the date and time to set. The wDayOfWeek field
  212. is ignored.
  213. Return Value:
  214. TRUE - The current system date and time was set.
  215. FALSE/NULL - The operation failed. Extended error status is available
  216. using GetLastError.
  217. --*/
  218. {
  219. LARGE_INTEGER SystemTime;
  220. LARGE_INTEGER LocalTime;
  221. TIME_FIELDS TimeFields;
  222. BOOLEAN ReturnValue;
  223. PVOID State;
  224. NTSTATUS Status;
  225. LARGE_INTEGER Bias;
  226. volatile KSYSTEM_TIME *pRealBias;
  227. //
  228. // Read time zone bias from shared region.
  229. // If it's terminal server session use client bias.
  230. if(IsTimeZoneRedirectionEnabled()) {
  231. pRealBias=&(BaseStaticServerData->ktTermsrvClientBias);
  232. } else {
  233. pRealBias=&(USER_SHARED_DATA->TimeZoneBias);
  234. }
  235. do {
  236. Bias.HighPart = pRealBias->High1Time;
  237. Bias.LowPart = pRealBias->LowPart;
  238. } while (Bias.HighPart != pRealBias->High2Time);
  239. ReturnValue = TRUE;
  240. TimeFields.Year = lpLocalTime->wYear ;
  241. TimeFields.Month = lpLocalTime->wMonth ;
  242. TimeFields.Day = lpLocalTime->wDay ;
  243. TimeFields.Hour = lpLocalTime->wHour ;
  244. TimeFields.Minute = lpLocalTime->wMinute ;
  245. TimeFields.Second = lpLocalTime->wSecond ;
  246. TimeFields.Milliseconds = lpLocalTime->wMilliseconds;
  247. if ( !RtlTimeFieldsToTime(&TimeFields,&LocalTime) ) {
  248. Status = STATUS_INVALID_PARAMETER;
  249. ReturnValue = FALSE;
  250. }
  251. else {
  252. SystemTime.QuadPart = LocalTime.QuadPart + Bias.QuadPart;
  253. Status = BasepAcquirePrivilegeEx( SE_SYSTEMTIME_PRIVILEGE, &State );
  254. if ( NT_SUCCESS(Status) ) {
  255. Status = NtSetSystemTime(&SystemTime,NULL);
  256. BasepReleasePrivilege( State );
  257. if ( !NT_SUCCESS(Status) ) {
  258. ReturnValue = FALSE;
  259. }
  260. }
  261. else {
  262. ReturnValue = FALSE;
  263. }
  264. }
  265. if ( !ReturnValue ) {
  266. BaseSetLastNTError(Status);
  267. }
  268. return ReturnValue;
  269. }
  270. DWORD
  271. GetTickCount(
  272. VOID
  273. )
  274. /*++
  275. Routine Description:
  276. Win32 systems implement a free-running millisecond counter. The
  277. value of this counter can be read using GetTickCount.
  278. Arguments:
  279. None.
  280. Return Value:
  281. This function returns the number of milliseconds that have elapsed
  282. since the system was started. If the system has been running for
  283. a long time, it is possible that the count will repeat. The value of
  284. the counter is accurate within 55 milliseconds.
  285. --*/
  286. {
  287. return (DWORD)NtGetTickCount();
  288. }
  289. BOOL
  290. APIENTRY
  291. FileTimeToSystemTime(
  292. CONST FILETIME *lpFileTime,
  293. LPSYSTEMTIME lpSystemTime
  294. )
  295. /*++
  296. Routine Description:
  297. This functions converts a 64-bit file time value to a time in system
  298. time format.
  299. Arguments:
  300. lpFileTime - Supplies the 64-bit file time to convert to the system
  301. date and time format.
  302. lpSystemTime - Returns the converted value of the 64-bit file time.
  303. Return Value:
  304. TRUE - The 64-bit file time was successfully converted.
  305. FALSE - The operation failed. Extended error status is available
  306. using GetLastError.
  307. --*/
  308. {
  309. LARGE_INTEGER FileTime;
  310. TIME_FIELDS TimeFields;
  311. FileTime.LowPart = lpFileTime->dwLowDateTime;
  312. FileTime.HighPart = lpFileTime->dwHighDateTime;
  313. if ( FileTime.QuadPart < 0 ) {
  314. SetLastError(ERROR_INVALID_PARAMETER);
  315. return FALSE;
  316. }
  317. RtlTimeToTimeFields(&FileTime, &TimeFields);
  318. lpSystemTime->wYear = TimeFields.Year ;
  319. lpSystemTime->wMonth = TimeFields.Month ;
  320. lpSystemTime->wDay = TimeFields.Day ;
  321. lpSystemTime->wDayOfWeek = TimeFields.Weekday ;
  322. lpSystemTime->wHour = TimeFields.Hour ;
  323. lpSystemTime->wMinute = TimeFields.Minute ;
  324. lpSystemTime->wSecond = TimeFields.Second ;
  325. lpSystemTime->wMilliseconds = TimeFields.Milliseconds;
  326. return TRUE;
  327. }
  328. BOOL
  329. APIENTRY
  330. SystemTimeToFileTime(
  331. CONST SYSTEMTIME *lpSystemTime,
  332. LPFILETIME lpFileTime
  333. )
  334. /*++
  335. Routine Description:
  336. This functions converts a system time value into a 64-bit file time.
  337. Arguments:
  338. lpSystemTime - Supplies the time that is to be converted into
  339. the 64-bit file time format. The wDayOfWeek field is ignored.
  340. lpFileTime - Returns the 64-bit file time representation of
  341. lpSystemTime.
  342. Return Value:
  343. TRUE - The time was successfully converted.
  344. FALSE - The operation failed. Extended error status is available
  345. using GetLastError.
  346. --*/
  347. {
  348. TIME_FIELDS TimeFields;
  349. LARGE_INTEGER FileTime;
  350. TimeFields.Year = lpSystemTime->wYear ;
  351. TimeFields.Month = lpSystemTime->wMonth ;
  352. TimeFields.Day = lpSystemTime->wDay ;
  353. TimeFields.Hour = lpSystemTime->wHour ;
  354. TimeFields.Minute = lpSystemTime->wMinute ;
  355. TimeFields.Second = lpSystemTime->wSecond ;
  356. TimeFields.Milliseconds = lpSystemTime->wMilliseconds;
  357. if ( !RtlTimeFieldsToTime(&TimeFields,&FileTime)) {
  358. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  359. return FALSE;
  360. }
  361. else {
  362. lpFileTime->dwLowDateTime = FileTime.LowPart;
  363. lpFileTime->dwHighDateTime = FileTime.HighPart;
  364. return TRUE;
  365. }
  366. }
  367. BOOL
  368. WINAPI
  369. FileTimeToLocalFileTime(
  370. CONST FILETIME *lpFileTime,
  371. LPFILETIME lpLocalFileTime
  372. )
  373. /*++
  374. Routine Description:
  375. This functions converts a UTC based file time to a local file time.
  376. Arguments:
  377. lpFileTime - Supplies the UTC based file time that is to be
  378. converted into a local file time
  379. lpLocalFileTime - Returns the 64-bit local file time representation of
  380. lpFileTime.
  381. Return Value:
  382. TRUE - The time was successfully converted.
  383. FALSE - The operation failed. Extended error status is available
  384. using GetLastError.
  385. --*/
  386. {
  387. LARGE_INTEGER FileTime;
  388. LARGE_INTEGER LocalFileTime;
  389. LARGE_INTEGER Bias;
  390. volatile KSYSTEM_TIME *pRealBias;
  391. //
  392. // Read time zone bias from shared region.
  393. // If it's terminal server session use client bias.
  394. if(IsTimeZoneRedirectionEnabled()) {
  395. pRealBias=&(BaseStaticServerData->ktTermsrvClientBias);
  396. } else {
  397. pRealBias=&(USER_SHARED_DATA->TimeZoneBias);
  398. }
  399. do {
  400. Bias.HighPart = pRealBias->High1Time;
  401. Bias.LowPart = pRealBias->LowPart;
  402. } while (Bias.HighPart != pRealBias->High2Time);
  403. FileTime.LowPart = lpFileTime->dwLowDateTime;
  404. FileTime.HighPart = lpFileTime->dwHighDateTime;
  405. LocalFileTime.QuadPart = FileTime.QuadPart - Bias.QuadPart;
  406. lpLocalFileTime->dwLowDateTime = LocalFileTime.LowPart;
  407. lpLocalFileTime->dwHighDateTime = LocalFileTime.HighPart;
  408. return TRUE;
  409. }
  410. BOOL
  411. WINAPI
  412. LocalFileTimeToFileTime(
  413. CONST FILETIME *lpLocalFileTime,
  414. LPFILETIME lpFileTime
  415. )
  416. /*++
  417. Routine Description:
  418. This functions converts a local file time to a UTC based file time.
  419. Arguments:
  420. lpLocalFileTime - Supplies the local file time that is to be
  421. converted into a UTC based file time
  422. lpFileTime - Returns the 64-bit UTC based file time representation of
  423. lpLocalFileTime.
  424. Return Value:
  425. TRUE - The time was successfully converted.
  426. FALSE - The operation failed. Extended error status is available
  427. using GetLastError.
  428. --*/
  429. {
  430. LARGE_INTEGER FileTime;
  431. LARGE_INTEGER LocalFileTime;
  432. LARGE_INTEGER Bias;
  433. volatile KSYSTEM_TIME *pRealBias;
  434. //
  435. // Read time zone bias from shared region.
  436. // If it's terminal server session use client bias.
  437. if(IsTimeZoneRedirectionEnabled()) {
  438. pRealBias=&(BaseStaticServerData->ktTermsrvClientBias);
  439. } else {
  440. pRealBias=&(USER_SHARED_DATA->TimeZoneBias);
  441. }
  442. do {
  443. Bias.HighPart = pRealBias->High1Time;
  444. Bias.LowPart = pRealBias->LowPart;
  445. } while (Bias.HighPart != pRealBias->High2Time);
  446. LocalFileTime.LowPart = lpLocalFileTime->dwLowDateTime;
  447. LocalFileTime.HighPart = lpLocalFileTime->dwHighDateTime;
  448. FileTime.QuadPart = LocalFileTime.QuadPart + Bias.QuadPart;
  449. lpFileTime->dwLowDateTime = FileTime.LowPart;
  450. lpFileTime->dwHighDateTime = FileTime.HighPart;
  451. return TRUE;
  452. }
  453. #define AlmostTwoSeconds (2*1000*1000*10 - 1)
  454. BOOL
  455. APIENTRY
  456. FileTimeToDosDateTime(
  457. CONST FILETIME *lpFileTime,
  458. LPWORD lpFatDate,
  459. LPWORD lpFatTime
  460. )
  461. /*++
  462. Routine Description:
  463. This function converts a 64-bit file time into DOS date and time value
  464. which is represented as two 16-bit unsigned integers.
  465. Since the DOS date format can only represent dates between 1/1/80 and
  466. 12/31/2107, this conversion can fail if the input file time is outside
  467. of this range.
  468. Arguments:
  469. lpFileTime - Supplies the 64-bit file time to convert to DOS date and
  470. time format.
  471. lpFatDate - Returns the 16-bit DOS representation of date.
  472. lpFatTime - Returns the 16-bit DOS representation of time.
  473. Return Value:
  474. TRUE - The file time was successfully converted.
  475. FALSE - The operation failed. Extended error status is available
  476. using GetLastError.
  477. --*/
  478. {
  479. TIME_FIELDS TimeFields;
  480. LARGE_INTEGER FileTime;
  481. FileTime.LowPart = lpFileTime->dwLowDateTime;
  482. FileTime.HighPart = lpFileTime->dwHighDateTime;
  483. FileTime.QuadPart = FileTime.QuadPart + (LONGLONG)AlmostTwoSeconds;
  484. if ( FileTime.QuadPart < 0 ) {
  485. SetLastError(ERROR_INVALID_PARAMETER);
  486. return FALSE;
  487. }
  488. RtlTimeToTimeFields(&FileTime, &TimeFields);
  489. if (TimeFields.Year < 1980 || TimeFields.Year > 2107) {
  490. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  491. return FALSE;
  492. }
  493. *lpFatDate = (WORD)( ((USHORT)(TimeFields.Year-(CSHORT)1980) << 9) |
  494. ((USHORT)TimeFields.Month << 5) |
  495. (USHORT)TimeFields.Day
  496. );
  497. *lpFatTime = (WORD)( ((USHORT)TimeFields.Hour << 11) |
  498. ((USHORT)TimeFields.Minute << 5) |
  499. ((USHORT)TimeFields.Second >> 1)
  500. );
  501. return TRUE;
  502. }
  503. BOOL
  504. APIENTRY
  505. DosDateTimeToFileTime(
  506. WORD wFatDate,
  507. WORD wFatTime,
  508. LPFILETIME lpFileTime
  509. )
  510. /*++
  511. Routine Description:
  512. This function converts a DOS date and time value, which is
  513. represented as two 16-bit unsigned integers, into a 64-bit file
  514. time.
  515. Arguments:
  516. lpFatDate - Supplies the 16-bit DOS representation of date.
  517. lpFatTime - Supplies the 16-bit DOS representation of time.
  518. lpFileTime - Returns the 64-bit file time converted from the DOS
  519. date and time format.
  520. Return Value:
  521. TRUE - The Dos date and time were successfully converted.
  522. FALSE - The operation failed. Extended error status is available
  523. using GetLastError.
  524. --*/
  525. {
  526. TIME_FIELDS TimeFields;
  527. LARGE_INTEGER FileTime;
  528. TimeFields.Year = (CSHORT)((wFatDate & 0xFE00) >> 9)+(CSHORT)1980;
  529. TimeFields.Month = (CSHORT)((wFatDate & 0x01E0) >> 5);
  530. TimeFields.Day = (CSHORT)((wFatDate & 0x001F) >> 0);
  531. TimeFields.Hour = (CSHORT)((wFatTime & 0xF800) >> 11);
  532. TimeFields.Minute = (CSHORT)((wFatTime & 0x07E0) >> 5);
  533. TimeFields.Second = (CSHORT)((wFatTime & 0x001F) << 1);
  534. TimeFields.Milliseconds = 0;
  535. if (RtlTimeFieldsToTime(&TimeFields,&FileTime)) {
  536. lpFileTime->dwLowDateTime = FileTime.LowPart;
  537. lpFileTime->dwHighDateTime = FileTime.HighPart;
  538. return TRUE;
  539. }
  540. else {
  541. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  542. return FALSE;
  543. }
  544. }
  545. LONG
  546. APIENTRY
  547. CompareFileTime(
  548. CONST FILETIME *lpFileTime1,
  549. CONST FILETIME *lpFileTime2
  550. )
  551. /*++
  552. Routine Description:
  553. This function compares two 64-bit file times.
  554. Arguments:
  555. lpFileTime1 - pointer to a 64-bit file time.
  556. lpFileTime2 - pointer to a 64-bit file time.
  557. Return Value:
  558. -1 - *lpFileTime1 < *lpFileTime2
  559. 0 - *lpFileTime1 == *lpFileTime2
  560. +1 - *lpFileTime1 > *lpFileTime2
  561. --*/
  562. {
  563. ULARGE_INTEGER FileTime1;
  564. ULARGE_INTEGER FileTime2;
  565. FileTime1.LowPart = lpFileTime1->dwLowDateTime;
  566. FileTime1.HighPart = lpFileTime1->dwHighDateTime;
  567. FileTime2.LowPart = lpFileTime2->dwLowDateTime;
  568. FileTime2.HighPart = lpFileTime2->dwHighDateTime;
  569. if (FileTime1.QuadPart < FileTime2.QuadPart) {
  570. return( -1 );
  571. }
  572. else
  573. if (FileTime1.QuadPart > FileTime2.QuadPart) {
  574. return( 1 );
  575. }
  576. else {
  577. return( 0 );
  578. }
  579. }
  580. DWORD
  581. WINAPI
  582. GetTimeZoneInformation(
  583. LPTIME_ZONE_INFORMATION lpTimeZoneInformation
  584. )
  585. /*++
  586. Routine Description:
  587. This function allows an application to get the current timezone
  588. parameters These parameters control the Universal time to Local time
  589. translations.
  590. All UTC time to Local time translations are based on the following
  591. formula:
  592. UTC = LocalTime + Bias
  593. The return value of this function is the systems best guess of
  594. the current time zone parameters. This is one of:
  595. - Unknown
  596. - Standard Time
  597. - Daylight Savings Time
  598. If SetTimeZoneInformation was called without the transition date
  599. information, Unknown is returned, but the currect bias is used for
  600. local time translation. Otherwise, the system will correctly pick
  601. either daylight savings time or standard time.
  602. The information returned by this API is identical to the information
  603. stored in the last successful call to SetTimeZoneInformation. The
  604. exception is the Bias field returns the current Bias value in
  605. Arguments:
  606. lpTimeZoneInformation - Supplies the address of the time zone
  607. information structure.
  608. Return Value:
  609. TIME_ZONE_ID_UNKNOWN - The system can not determine the current
  610. timezone. This is usually due to a previous call to
  611. SetTimeZoneInformation where only the Bias was supplied and no
  612. transition dates were supplied.
  613. TIME_ZONE_ID_STANDARD - The system is operating in the range covered
  614. by StandardDate.
  615. TIME_ZONE_ID_DAYLIGHT - The system is operating in the range covered
  616. by DaylightDate.
  617. 0xffffffff - The operation failed. Extended error status is
  618. available using GetLastError.
  619. --*/
  620. {
  621. RTL_TIME_ZONE_INFORMATION tzi;
  622. NTSTATUS Status;
  623. //
  624. // get the timezone data from the system
  625. // If it's terminal server session use client time zone
  626. if(IsTimeZoneRedirectionEnabled()) {
  627. *lpTimeZoneInformation = BaseStaticServerData->tziTermsrvClientTimeZone;
  628. return BaseStaticServerData->TermsrvClientTimeZoneId;
  629. } else {
  630. Status = NtQuerySystemInformation(
  631. SystemCurrentTimeZoneInformation,
  632. &tzi,
  633. sizeof(tzi),
  634. NULL
  635. );
  636. if ( !NT_SUCCESS(Status) ) {
  637. BaseSetLastNTError(Status);
  638. return 0xffffffff;
  639. }
  640. lpTimeZoneInformation->Bias = tzi.Bias;
  641. lpTimeZoneInformation->StandardBias = tzi.StandardBias;
  642. lpTimeZoneInformation->DaylightBias = tzi.DaylightBias;
  643. RtlCopyMemory(&lpTimeZoneInformation->StandardName,&tzi.StandardName,sizeof(tzi.StandardName));
  644. RtlCopyMemory(&lpTimeZoneInformation->DaylightName,&tzi.DaylightName,sizeof(tzi.DaylightName));
  645. lpTimeZoneInformation->StandardDate.wYear = tzi.StandardStart.Year ;
  646. lpTimeZoneInformation->StandardDate.wMonth = tzi.StandardStart.Month ;
  647. lpTimeZoneInformation->StandardDate.wDayOfWeek = tzi.StandardStart.Weekday ;
  648. lpTimeZoneInformation->StandardDate.wDay = tzi.StandardStart.Day ;
  649. lpTimeZoneInformation->StandardDate.wHour = tzi.StandardStart.Hour ;
  650. lpTimeZoneInformation->StandardDate.wMinute = tzi.StandardStart.Minute ;
  651. lpTimeZoneInformation->StandardDate.wSecond = tzi.StandardStart.Second ;
  652. lpTimeZoneInformation->StandardDate.wMilliseconds = tzi.StandardStart.Milliseconds;
  653. lpTimeZoneInformation->DaylightDate.wYear = tzi.DaylightStart.Year ;
  654. lpTimeZoneInformation->DaylightDate.wMonth = tzi.DaylightStart.Month ;
  655. lpTimeZoneInformation->DaylightDate.wDayOfWeek = tzi.DaylightStart.Weekday ;
  656. lpTimeZoneInformation->DaylightDate.wDay = tzi.DaylightStart.Day ;
  657. lpTimeZoneInformation->DaylightDate.wHour = tzi.DaylightStart.Hour ;
  658. lpTimeZoneInformation->DaylightDate.wMinute = tzi.DaylightStart.Minute ;
  659. lpTimeZoneInformation->DaylightDate.wSecond = tzi.DaylightStart.Second ;
  660. lpTimeZoneInformation->DaylightDate.wMilliseconds = tzi.DaylightStart.Milliseconds;
  661. return USER_SHARED_DATA->TimeZoneId;
  662. }
  663. }
  664. BOOL
  665. WINAPI
  666. SetTimeZoneInformation(
  667. CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation
  668. )
  669. /*++
  670. Routine Description:
  671. This function allows an application to set timezone parameters into
  672. their system. These parameters control the Universal time to Local
  673. time translations.
  674. All UTC time to Local time translations are based on the following
  675. formula:
  676. UTC = LocalTime + Bias
  677. This API allows the caller to program the current time zone bias,
  678. and optionally set up the system to automatically sense daylight
  679. savings time and standard time transitions.
  680. The timezone bias information is controlled by the
  681. TIME_ZONE_INFORMATION structure.
  682. Bias - Supplies the current bias in minutes for local time
  683. translation on this machine where LocalTime + Bias = UTC. This
  684. is a required filed of this structure.
  685. StandardName - Supplies an optional abbreviation string associated
  686. with standard time on this system. This string is uniterpreted
  687. and is supplied and used only by callers of this API and of
  688. GetTimeZoneInformation.
  689. StandardDate - Supplies an optional date and time (UTC) that
  690. describes the transition into standard time. A value of 0 in
  691. the wMonth field tells the system that StandardDate is not
  692. specified. If this field is specified, then DaylightDate must
  693. also be specified. Additionally, local time translations done
  694. during the StandardTime range will be done relative to the
  695. supplied StandardBias value (added to Bias).
  696. This field supports two date formats. Absolute form specifies and
  697. exact date and time when standard time begins. In this form, the
  698. wYear, wMonth, wDay, wHour, wMinute, wSecond, and wMilliseconds
  699. of the SYSTEMTIME structure are used to specify an exact date.
  700. Day-in-month time is specified by setting wYear to 0, setting
  701. wDayOfWeek to an appropriate weekday, and using wDay in the
  702. range of 1-5 to select the correct day in the month. Using this
  703. notation, the first sunday in april may be specified as can be
  704. the last thursday in october (5 is equal to "the last").
  705. StandardBias - Supplies an optional bias value to be used during
  706. local time translations that occur during Standard Time. This
  707. field is ignored if StandardDate is not supplied.
  708. This bias value
  709. is added to the Bias field to form the Bias used during standard
  710. time. In most time zones, the value of this field is zero.
  711. DaylightName - Supplies an optional abbreviation string associated
  712. with daylight savings time on this system. This string is
  713. uniterpreted and is supplied and used only by callers of this
  714. API and of GetTimeZoneInformation.
  715. DaylightDate - Supplies an optional date and time (UTC) that
  716. describes the transition into daylight savings time. A value of
  717. 0 in the wMonth field tells the system that DaylightDate is not
  718. specified. If this field is specified, then StandardDate must
  719. also be specified. Additionally, local time translations done
  720. during the DaylightTime range will be done relative to the
  721. supplied DaylightBias value (added to Bias). The same dat formats
  722. supported by StandardDate are supported ib DaylightDate.
  723. DaylightBias - Supplies an optional bias value to be used during
  724. local time translations that occur during Daylight Savings Time.
  725. This field is ignored if DaylightDate is not supplied. This
  726. bias value is added to the Bias field to form the Bias used
  727. during daylight time. In most time zones, the value of this
  728. field is -60.
  729. Arguments:
  730. lpTimeZoneInformation - Supplies the address of the time zone
  731. information structure.
  732. Return Value:
  733. TRUE - The operation was successful.
  734. FALSE - The operation failed. Extended error status is available
  735. using GetLastError.
  736. --*/
  737. {
  738. RTL_TIME_ZONE_INFORMATION tzi;
  739. NTSTATUS Status;
  740. if(IsTimeZoneRedirectionEnabled()) {
  741. return SetClientTimeZoneInformation(lpTimeZoneInformation);
  742. } else {
  743. tzi.Bias = lpTimeZoneInformation->Bias;
  744. tzi.StandardBias = lpTimeZoneInformation->StandardBias;
  745. tzi.DaylightBias = lpTimeZoneInformation->DaylightBias;
  746. RtlCopyMemory(&tzi.StandardName,&lpTimeZoneInformation->StandardName,sizeof(tzi.StandardName));
  747. RtlCopyMemory(&tzi.DaylightName,&lpTimeZoneInformation->DaylightName,sizeof(tzi.DaylightName));
  748. tzi.StandardStart.Year = lpTimeZoneInformation->StandardDate.wYear ;
  749. tzi.StandardStart.Month = lpTimeZoneInformation->StandardDate.wMonth ;
  750. tzi.StandardStart.Weekday = lpTimeZoneInformation->StandardDate.wDayOfWeek ;
  751. tzi.StandardStart.Day = lpTimeZoneInformation->StandardDate.wDay ;
  752. tzi.StandardStart.Hour = lpTimeZoneInformation->StandardDate.wHour ;
  753. tzi.StandardStart.Minute = lpTimeZoneInformation->StandardDate.wMinute ;
  754. tzi.StandardStart.Second = lpTimeZoneInformation->StandardDate.wSecond ;
  755. tzi.StandardStart.Milliseconds = lpTimeZoneInformation->StandardDate.wMilliseconds;
  756. tzi.DaylightStart.Year = lpTimeZoneInformation->DaylightDate.wYear ;
  757. tzi.DaylightStart.Month = lpTimeZoneInformation->DaylightDate.wMonth ;
  758. tzi.DaylightStart.Weekday = lpTimeZoneInformation->DaylightDate.wDayOfWeek ;
  759. tzi.DaylightStart.Day = lpTimeZoneInformation->DaylightDate.wDay ;
  760. tzi.DaylightStart.Hour = lpTimeZoneInformation->DaylightDate.wHour ;
  761. tzi.DaylightStart.Minute = lpTimeZoneInformation->DaylightDate.wMinute ;
  762. tzi.DaylightStart.Second = lpTimeZoneInformation->DaylightDate.wSecond ;
  763. tzi.DaylightStart.Milliseconds = lpTimeZoneInformation->DaylightDate.wMilliseconds;
  764. Status = RtlSetTimeZoneInformation( &tzi );
  765. if (!NT_SUCCESS( Status )) {
  766. BaseSetLastNTError(Status);
  767. return FALSE;
  768. }
  769. //
  770. // Refresh the system's concept of time
  771. //
  772. NtSetSystemTime(NULL,NULL);
  773. return TRUE;
  774. }
  775. }
  776. BOOL
  777. WINAPI
  778. GetSystemTimeAdjustment(
  779. PDWORD lpTimeAdjustment,
  780. PDWORD lpTimeIncrement,
  781. PBOOL lpTimeAdjustmentDisabled
  782. )
  783. /*++
  784. Routine Description:
  785. This function is used to support algorithms that want to synchronize
  786. the time of day (reported via GetSystemTime and GetLocalTime) with
  787. another time source using a programmed clock adjustment over a
  788. period of time.
  789. To facilitate this, the system computes the time of day by adding a
  790. value to a time of day counter at a periodic interval. This API
  791. allows the caller to obtain the periodic interval (clock interrupt
  792. rate), and the amount added to the time of day with each interrupt.
  793. A boolean value is also returned which indicates whether or not this
  794. time adjustment algorithm is even being used. A value of TRUE
  795. indicates that adjustment is not being used. If this is the case,
  796. the system may attempt to keep the time of day clock in sync using
  797. its own internal mechanisms. This may cause time of day to
  798. periodicly "jump" to the "correct time".
  799. Arguments:
  800. lpTimeAdjustment - Returns the number of 100ns units added to the
  801. time of day counter at each clock interrupt.
  802. lpTimeIncrement - Returns the clock interrupt rate in 100ns units.
  803. lpTimeAdjustmentDisabled - Returns an indicator which specifies
  804. whether or not time adjustment is inabled. A value of TRUE
  805. indicates that periodic adjustment is disabled
  806. (*lpTimeAdjustment == *lpTimeIncrement), AND that the system is
  807. free to serialize time of day using any mechanism it wants.
  808. This may cause periodic time jumps as the system serializes time
  809. of day to the "correct time". A value of false indicates that
  810. programmed time adjustment is being used to serialize the time
  811. of day, and that the system will not interfere with this scheme
  812. and will not attempt to synchronize time of day on its own.
  813. Return Value:
  814. TRUE - The operation was successful.
  815. FALSE - The operation failed. Use GetLastError to obtain detailed
  816. error information.
  817. --*/
  818. {
  819. NTSTATUS Status;
  820. SYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeAdjust;
  821. BOOL b;
  822. Status = NtQuerySystemInformation(
  823. SystemTimeAdjustmentInformation,
  824. &TimeAdjust,
  825. sizeof(TimeAdjust),
  826. NULL
  827. );
  828. if ( !NT_SUCCESS(Status) ) {
  829. BaseSetLastNTError(Status);
  830. b = FALSE;
  831. }
  832. else {
  833. *lpTimeAdjustment = TimeAdjust.TimeAdjustment;
  834. *lpTimeIncrement = TimeAdjust.TimeIncrement;
  835. *lpTimeAdjustmentDisabled = TimeAdjust.Enable;
  836. b = TRUE;
  837. }
  838. return b;
  839. }
  840. BOOL
  841. WINAPI
  842. SetSystemTimeAdjustment(
  843. DWORD dwTimeAdjustment,
  844. BOOL bTimeAdjustmentDisabled
  845. )
  846. /*++
  847. Routine Description:
  848. This function is used to tell the system the parameters it should
  849. use to periodicaly synchronize time of day with some other source.
  850. This API supports two modes of operation.
  851. In the first mode, bTimeAdjustmentDisabled is set to FALSE. At each
  852. clock interrupt, the value of dwTimeAdjustment is added to the time
  853. of day. The clock interrupt rate may be obtained using
  854. GetSystemTimeAdjustment, and looking at the returned value of
  855. lpTimeIncrement.
  856. In the second mode, bTimeAdjustmentDisabled is set to TRUE. At each
  857. clock interrupt, the clock interrupt rate is added to the time of
  858. day. The system may also periodically refresh the time of day using
  859. other internal algorithms. These may produce "jumps" in time.
  860. The application must have system-time privilege (the
  861. SE_SYSTEMTIME_NAME privilege) for this function to succeed. This
  862. privilege is disabled by default. Use the AdjustTokenPrivileges
  863. function to enable the privilege and again to disable it after the
  864. time adjustment has been set.
  865. Arguments:
  866. dwTimeAdjustment - Supplies the value (in 100ns units) that is to be
  867. added to the time of day at each clock interrupt.
  868. bTimeAdjustmentDisabled - Supplies a flag which specifies the time
  869. adjustment mode that the system is to use. A value of TRUE
  870. indicates the the system should synchronize time of day using
  871. its own internal mechanisms. When this is the case, the value
  872. of dwTimeAdjustment is ignored. A value of FALSE indicates that
  873. the application is in control, and that the value specified by
  874. dwTimeAdjustment is to be added to the time of day at each clock
  875. interrupt.
  876. Return Value:
  877. TRUE - The operation was successful.
  878. FALSE - The operation failed. Use GetLastError to obtain detailed
  879. error information.
  880. --*/
  881. {
  882. NTSTATUS Status;
  883. SYSTEM_SET_TIME_ADJUST_INFORMATION TimeAdjust;
  884. BOOL b;
  885. b = TRUE;
  886. TimeAdjust.TimeAdjustment = dwTimeAdjustment;
  887. TimeAdjust.Enable = (BOOLEAN)bTimeAdjustmentDisabled;
  888. Status = NtSetSystemInformation(
  889. SystemTimeAdjustmentInformation,
  890. &TimeAdjust,
  891. sizeof(TimeAdjust)
  892. );
  893. if ( !NT_SUCCESS(Status) ) {
  894. BaseSetLastNTError(Status);
  895. b = FALSE;
  896. }
  897. return b;
  898. }
  899. BOOL
  900. WINAPI
  901. SystemTimeToTzSpecificLocalTime(
  902. LPTIME_ZONE_INFORMATION lpTimeZoneInformation,
  903. LPSYSTEMTIME lpUniversalTime,
  904. LPSYSTEMTIME lpLocalTime
  905. )
  906. {
  907. TIME_ZONE_INFORMATION TziData;
  908. LPTIME_ZONE_INFORMATION Tzi;
  909. RTL_TIME_ZONE_INFORMATION tzi;
  910. LARGE_INTEGER TimeZoneBias;
  911. LARGE_INTEGER NewTimeZoneBias;
  912. LARGE_INTEGER LocalCustomBias;
  913. LARGE_INTEGER StandardTime;
  914. LARGE_INTEGER DaylightTime;
  915. LARGE_INTEGER UtcStandardTime;
  916. LARGE_INTEGER UtcDaylightTime;
  917. LARGE_INTEGER CurrentUniversalTime;
  918. LARGE_INTEGER ComputedLocalTime;
  919. ULONG CurrentTimeZoneId = 0xffffffff;
  920. //
  921. // Get the timezone information into a useful format
  922. //
  923. if ( !ARGUMENT_PRESENT(lpTimeZoneInformation) ) {
  924. //
  925. // Convert universal time to local time using current timezone info
  926. //
  927. if (GetTimeZoneInformation(&TziData) == TIME_ZONE_ID_INVALID) {
  928. return FALSE;
  929. }
  930. Tzi = &TziData;
  931. } else {
  932. Tzi = lpTimeZoneInformation;
  933. }
  934. tzi.Bias = Tzi->Bias;
  935. tzi.StandardBias = Tzi->StandardBias;
  936. tzi.DaylightBias = Tzi->DaylightBias;
  937. RtlCopyMemory(&tzi.StandardName,&Tzi->StandardName,sizeof(tzi.StandardName));
  938. RtlCopyMemory(&tzi.DaylightName,&Tzi->DaylightName,sizeof(tzi.DaylightName));
  939. tzi.StandardStart.Year = Tzi->StandardDate.wYear ;
  940. tzi.StandardStart.Month = Tzi->StandardDate.wMonth ;
  941. tzi.StandardStart.Weekday = Tzi->StandardDate.wDayOfWeek ;
  942. tzi.StandardStart.Day = Tzi->StandardDate.wDay ;
  943. tzi.StandardStart.Hour = Tzi->StandardDate.wHour ;
  944. tzi.StandardStart.Minute = Tzi->StandardDate.wMinute ;
  945. tzi.StandardStart.Second = Tzi->StandardDate.wSecond ;
  946. tzi.StandardStart.Milliseconds = Tzi->StandardDate.wMilliseconds;
  947. tzi.DaylightStart.Year = Tzi->DaylightDate.wYear ;
  948. tzi.DaylightStart.Month = Tzi->DaylightDate.wMonth ;
  949. tzi.DaylightStart.Weekday = Tzi->DaylightDate.wDayOfWeek ;
  950. tzi.DaylightStart.Day = Tzi->DaylightDate.wDay ;
  951. tzi.DaylightStart.Hour = Tzi->DaylightDate.wHour ;
  952. tzi.DaylightStart.Minute = Tzi->DaylightDate.wMinute ;
  953. tzi.DaylightStart.Second = Tzi->DaylightDate.wSecond ;
  954. tzi.DaylightStart.Milliseconds = Tzi->DaylightDate.wMilliseconds;
  955. //
  956. // convert the input universal time to NT style time
  957. //
  958. if ( !SystemTimeToFileTime(lpUniversalTime,(LPFILETIME)&CurrentUniversalTime) ) {
  959. return FALSE;
  960. }
  961. //
  962. // Get the new timezone bias
  963. //
  964. NewTimeZoneBias.QuadPart = Int32x32To64(tzi.Bias*60, 10000000);
  965. //
  966. // Now see if we have stored cutover times
  967. //
  968. if ( tzi.StandardStart.Month && tzi.DaylightStart.Month ) {
  969. //
  970. // We have timezone cutover information. Compute the
  971. // cutover dates and compute what our current bias
  972. // is
  973. //
  974. if ( !RtlCutoverTimeToSystemTime(
  975. &tzi.StandardStart,
  976. &StandardTime,
  977. &CurrentUniversalTime,
  978. TRUE
  979. ) ) {
  980. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  981. return FALSE;
  982. }
  983. if ( !RtlCutoverTimeToSystemTime(
  984. &tzi.DaylightStart,
  985. &DaylightTime,
  986. &CurrentUniversalTime,
  987. TRUE
  988. ) ) {
  989. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  990. return FALSE;
  991. }
  992. //
  993. // Convert standard time and daylight time to utc
  994. //
  995. LocalCustomBias.QuadPart = Int32x32To64(tzi.StandardBias*60, 10000000);
  996. TimeZoneBias.QuadPart = NewTimeZoneBias.QuadPart + LocalCustomBias.QuadPart;
  997. UtcDaylightTime.QuadPart = DaylightTime.QuadPart + TimeZoneBias.QuadPart;
  998. LocalCustomBias.QuadPart = Int32x32To64(tzi.DaylightBias*60, 10000000);
  999. TimeZoneBias.QuadPart = NewTimeZoneBias.QuadPart + LocalCustomBias.QuadPart;
  1000. UtcStandardTime.QuadPart = StandardTime.QuadPart + TimeZoneBias.QuadPart;
  1001. //
  1002. // If daylight < standard, then time >= daylight and
  1003. // less than standard is daylight
  1004. //
  1005. if ( UtcDaylightTime.QuadPart < UtcStandardTime.QuadPart ) {
  1006. //
  1007. // If today is >= DaylightTime and < StandardTime, then
  1008. // We are in daylight savings time
  1009. //
  1010. if ( (CurrentUniversalTime.QuadPart >= UtcDaylightTime.QuadPart) &&
  1011. (CurrentUniversalTime.QuadPart < UtcStandardTime.QuadPart) ) {
  1012. CurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT;
  1013. }
  1014. else {
  1015. CurrentTimeZoneId = TIME_ZONE_ID_STANDARD;
  1016. }
  1017. }
  1018. else {
  1019. //
  1020. // If today is >= StandardTime and < DaylightTime, then
  1021. // We are in standard time
  1022. //
  1023. if ( (CurrentUniversalTime.QuadPart >= UtcStandardTime.QuadPart ) &&
  1024. (CurrentUniversalTime.QuadPart < UtcDaylightTime.QuadPart ) ) {
  1025. CurrentTimeZoneId = TIME_ZONE_ID_STANDARD;
  1026. }
  1027. else {
  1028. CurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT;
  1029. }
  1030. }
  1031. //
  1032. // At this point, we know our current timezone and the
  1033. // Universal time of the next cutover.
  1034. //
  1035. LocalCustomBias.QuadPart = Int32x32To64(
  1036. CurrentTimeZoneId == TIME_ZONE_ID_DAYLIGHT ?
  1037. tzi.DaylightBias*60 :
  1038. tzi.StandardBias*60, // Bias in seconds
  1039. 10000000
  1040. );
  1041. TimeZoneBias.QuadPart = NewTimeZoneBias.QuadPart + LocalCustomBias.QuadPart;
  1042. }
  1043. else {
  1044. TimeZoneBias = NewTimeZoneBias;
  1045. }
  1046. ComputedLocalTime.QuadPart = CurrentUniversalTime.QuadPart - TimeZoneBias.QuadPart;
  1047. if ( !FileTimeToSystemTime((LPFILETIME)&ComputedLocalTime,lpLocalTime) ) {
  1048. return FALSE;
  1049. }
  1050. return TRUE;
  1051. }
  1052. BOOL
  1053. WINAPI
  1054. TzSpecificLocalTimeToSystemTime(
  1055. LPTIME_ZONE_INFORMATION lpTimeZoneInformation,
  1056. LPSYSTEMTIME lpLocalTime,
  1057. LPSYSTEMTIME lpUniversalTime
  1058. )
  1059. {
  1060. TIME_ZONE_INFORMATION TziData;
  1061. LPTIME_ZONE_INFORMATION Tzi;
  1062. RTL_TIME_ZONE_INFORMATION tzi;
  1063. LARGE_INTEGER TimeZoneBias;
  1064. LARGE_INTEGER NewTimeZoneBias;
  1065. LARGE_INTEGER LocalCustomBias;
  1066. LARGE_INTEGER StandardTime;
  1067. LARGE_INTEGER DaylightTime;
  1068. LARGE_INTEGER CurrentLocalTime;
  1069. LARGE_INTEGER ComputedUniversalTime;
  1070. ULONG CurrentTimeZoneId = 0xffffffff;
  1071. //
  1072. // Get the timezone information into a useful format
  1073. //
  1074. if ( !ARGUMENT_PRESENT(lpTimeZoneInformation) ) {
  1075. //
  1076. // Convert universal time to local time using current timezone info
  1077. //
  1078. if (GetTimeZoneInformation(&TziData) == TIME_ZONE_ID_INVALID) {
  1079. return FALSE;
  1080. }
  1081. Tzi = &TziData;
  1082. }
  1083. else {
  1084. Tzi = lpTimeZoneInformation;
  1085. }
  1086. tzi.Bias = Tzi->Bias;
  1087. tzi.StandardBias = Tzi->StandardBias;
  1088. tzi.DaylightBias = Tzi->DaylightBias;
  1089. RtlCopyMemory(&tzi.StandardName,&Tzi->StandardName,sizeof(tzi.StandardName));
  1090. RtlCopyMemory(&tzi.DaylightName,&Tzi->DaylightName,sizeof(tzi.DaylightName));
  1091. tzi.StandardStart.Year = Tzi->StandardDate.wYear ;
  1092. tzi.StandardStart.Month = Tzi->StandardDate.wMonth ;
  1093. tzi.StandardStart.Weekday = Tzi->StandardDate.wDayOfWeek ;
  1094. tzi.StandardStart.Day = Tzi->StandardDate.wDay ;
  1095. tzi.StandardStart.Hour = Tzi->StandardDate.wHour ;
  1096. tzi.StandardStart.Minute = Tzi->StandardDate.wMinute ;
  1097. tzi.StandardStart.Second = Tzi->StandardDate.wSecond ;
  1098. tzi.StandardStart.Milliseconds = Tzi->StandardDate.wMilliseconds;
  1099. tzi.DaylightStart.Year = Tzi->DaylightDate.wYear ;
  1100. tzi.DaylightStart.Month = Tzi->DaylightDate.wMonth ;
  1101. tzi.DaylightStart.Weekday = Tzi->DaylightDate.wDayOfWeek ;
  1102. tzi.DaylightStart.Day = Tzi->DaylightDate.wDay ;
  1103. tzi.DaylightStart.Hour = Tzi->DaylightDate.wHour ;
  1104. tzi.DaylightStart.Minute = Tzi->DaylightDate.wMinute ;
  1105. tzi.DaylightStart.Second = Tzi->DaylightDate.wSecond ;
  1106. tzi.DaylightStart.Milliseconds = Tzi->DaylightDate.wMilliseconds;
  1107. //
  1108. // convert the input local time to NT style time
  1109. //
  1110. if ( !SystemTimeToFileTime(lpLocalTime,(LPFILETIME)&CurrentLocalTime) ) {
  1111. return FALSE;
  1112. }
  1113. //
  1114. // Get the new timezone bias
  1115. //
  1116. NewTimeZoneBias.QuadPart = Int32x32To64(tzi.Bias*60, 10000000);
  1117. //
  1118. // Now see if we have stored cutover times
  1119. //
  1120. if ( tzi.StandardStart.Month && tzi.DaylightStart.Month ) {
  1121. //
  1122. // We have timezone cutover information. Compute the
  1123. // cutover dates and compute what our current bias
  1124. // is
  1125. //
  1126. if ( !RtlCutoverTimeToSystemTime(
  1127. &tzi.StandardStart,
  1128. &StandardTime,
  1129. &CurrentLocalTime,
  1130. TRUE
  1131. ) ) {
  1132. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  1133. return FALSE;
  1134. }
  1135. if ( !RtlCutoverTimeToSystemTime(
  1136. &tzi.DaylightStart,
  1137. &DaylightTime,
  1138. &CurrentLocalTime,
  1139. TRUE
  1140. ) ) {
  1141. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  1142. return FALSE;
  1143. }
  1144. //
  1145. // If daylight < standard, then time >= daylight and
  1146. // less than standard is daylight
  1147. //
  1148. if ( DaylightTime.QuadPart < StandardTime.QuadPart ) {
  1149. //
  1150. // If today is >= DaylightTime and < StandardTime, then
  1151. // We are in daylight savings time
  1152. //
  1153. if ( (CurrentLocalTime.QuadPart >= DaylightTime.QuadPart) &&
  1154. (CurrentLocalTime.QuadPart < StandardTime.QuadPart) ) {
  1155. CurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT;
  1156. }
  1157. else {
  1158. CurrentTimeZoneId = TIME_ZONE_ID_STANDARD;
  1159. }
  1160. }
  1161. else {
  1162. //
  1163. // If today is >= StandardTime and < DaylightTime, then
  1164. // We are in standard time
  1165. //
  1166. if ( (CurrentLocalTime.QuadPart >= StandardTime.QuadPart ) &&
  1167. (CurrentLocalTime.QuadPart < DaylightTime.QuadPart ) ) {
  1168. CurrentTimeZoneId = TIME_ZONE_ID_STANDARD;
  1169. }
  1170. else {
  1171. CurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT;
  1172. }
  1173. }
  1174. //
  1175. // At this point, we know our current timezone and the
  1176. // local time of the next cutover.
  1177. //
  1178. LocalCustomBias.QuadPart = Int32x32To64(
  1179. CurrentTimeZoneId == TIME_ZONE_ID_DAYLIGHT ?
  1180. tzi.DaylightBias*60 :
  1181. tzi.StandardBias*60, // Bias in seconds
  1182. 10000000
  1183. );
  1184. TimeZoneBias.QuadPart = NewTimeZoneBias.QuadPart + LocalCustomBias.QuadPart;
  1185. }
  1186. else {
  1187. TimeZoneBias = NewTimeZoneBias;
  1188. }
  1189. ComputedUniversalTime.QuadPart = CurrentLocalTime.QuadPart + TimeZoneBias.QuadPart;
  1190. if ( !FileTimeToSystemTime((LPFILETIME)&ComputedUniversalTime,lpUniversalTime) ) {
  1191. return FALSE;
  1192. }
  1193. return TRUE;
  1194. }
  1195. BOOL
  1196. WINAPI
  1197. SetClientTimeZoneInformation(
  1198. IN CONST TIME_ZONE_INFORMATION *ptzi
  1199. )
  1200. /*++
  1201. Routine Description:
  1202. Sets information in global structures used
  1203. to calculate local time in TS session.
  1204. Arguments:
  1205. IN CONST TIME_ZONE_INFORMATION *ptzi
  1206. Return Value:
  1207. TRUE - The operation was successful.
  1208. FALSE - The operation failed. Use GetLastError to obtain detailed
  1209. error information.
  1210. Client time zone information may become invalid during this call
  1211. In this case we will use time zone information from server
  1212. --*/
  1213. {
  1214. NTSTATUS Status;
  1215. BASE_API_MSG m;
  1216. PBASE_SET_TERMSRVCLIENTTIMEZONE c = &m.u.SetTermsrvClientTimeZone;
  1217. c->fFirstChunk=TRUE; //this meanes that this is only first portion of data
  1218. //we have to cut it ito two pieces because of
  1219. //message size restrictions (100 bytes)
  1220. c->Bias=ptzi->Bias;
  1221. RtlCopyMemory(&c->Name,&ptzi->StandardName,sizeof(ptzi->StandardName));
  1222. c->Date=ptzi->StandardDate;
  1223. c->Bias1=ptzi->StandardBias;
  1224. #if defined(BUILD_WOW6432)
  1225. Status = CsrBasepSetClientTimeZoneInformation(c);
  1226. #else
  1227. Status = CsrClientCallServer((PCSR_API_MSG)&m, NULL,
  1228. CSR_MAKE_API_NUMBER(BASESRV_SERVERDLL_INDEX,
  1229. BasepSetTermsrvClientTimeZone),
  1230. sizeof( *c ));
  1231. #endif
  1232. if ( !NT_SUCCESS( Status ) ) {
  1233. SetLastError( RtlNtStatusToDosError( Status ) );
  1234. return( FALSE );
  1235. }
  1236. c->fFirstChunk=FALSE; //this is a second and last portion of data
  1237. RtlCopyMemory(&c->Name,&ptzi->DaylightName,sizeof(ptzi->DaylightName));
  1238. c->Date=ptzi->DaylightDate;
  1239. c->Bias1=ptzi->DaylightBias;
  1240. c->TimeZoneId=CalcClientTimeZoneIdAndBias(ptzi,&c->RealBias);
  1241. #if defined(BUILD_WOW6432)
  1242. Status = CsrBasepSetClientTimeZoneInformation(c);
  1243. #else
  1244. Status = CsrClientCallServer((PCSR_API_MSG)&m, NULL,
  1245. CSR_MAKE_API_NUMBER(BASESRV_SERVERDLL_INDEX,
  1246. BasepSetTermsrvClientTimeZone),
  1247. sizeof( *c ));
  1248. #endif
  1249. if ( !NT_SUCCESS( Status ) ) {
  1250. SetLastError( RtlNtStatusToDosError( Status ) );
  1251. return( FALSE );
  1252. }
  1253. return( TRUE );
  1254. }
  1255. ULONG
  1256. CalcClientTimeZoneIdAndBias(
  1257. IN CONST TIME_ZONE_INFORMATION *ptzi,
  1258. OUT KSYSTEM_TIME *pBias)
  1259. /*++
  1260. Routine Description:
  1261. Calculates current bias and time zone ID.
  1262. Arguments:
  1263. IN CONST TIME_ZONE_INFORMATION *ptzi - time zone for which to calculate bias
  1264. OUT KSYSTEM_TIME *pBias - current bias
  1265. Return Value:
  1266. TIME_ZONE_ID_UNKNOWN - daylight saving time is not used in the
  1267. current time zone.
  1268. TIME_ZONE_ID_STANDARD - The system is operating in the range covered
  1269. by StandardDate.
  1270. TIME_ZONE_ID_DAYLIGHT - The system is operating in the range covered
  1271. by DaylightDate.
  1272. TIME_ZONE_ID_INVALID - The operation failed. Extended error status is
  1273. available using GetLastError.
  1274. --*/
  1275. {
  1276. LARGE_INTEGER TimeZoneBias;
  1277. LARGE_INTEGER NewTimeZoneBias;
  1278. LARGE_INTEGER LocalCustomBias;
  1279. LARGE_INTEGER StandardTime;
  1280. LARGE_INTEGER DaylightTime;
  1281. LARGE_INTEGER UtcStandardTime;
  1282. LARGE_INTEGER UtcDaylightTime;
  1283. SYSTEMTIME CurrentSystemTime;
  1284. LARGE_INTEGER CurrentUniversalTime;
  1285. ULONG CurrentTimeZoneId = 0xffffffff;
  1286. TIME_FIELDS StandardStart,DaylightStart;
  1287. NewTimeZoneBias.QuadPart = Int32x32To64(ptzi->Bias*60, 10000000);
  1288. //
  1289. // Now see if we have stored cutover times
  1290. //
  1291. if ( ptzi->StandardDate.wMonth && ptzi->DaylightDate.wMonth ) {
  1292. GetSystemTime(&CurrentSystemTime);
  1293. SystemTimeToFileTime(&CurrentSystemTime,(LPFILETIME)&CurrentUniversalTime);
  1294. StandardStart.Year = ptzi->StandardDate.wYear ;
  1295. StandardStart.Month = ptzi->StandardDate.wMonth ;
  1296. StandardStart.Weekday = ptzi->StandardDate.wDayOfWeek ;
  1297. StandardStart.Day = ptzi->StandardDate.wDay ;
  1298. StandardStart.Hour = ptzi->StandardDate.wHour ;
  1299. StandardStart.Minute = ptzi->StandardDate.wMinute ;
  1300. StandardStart.Second = ptzi->StandardDate.wSecond ;
  1301. StandardStart.Milliseconds = ptzi->StandardDate.wMilliseconds;
  1302. DaylightStart.Year = ptzi->DaylightDate.wYear ;
  1303. DaylightStart.Month = ptzi->DaylightDate.wMonth ;
  1304. DaylightStart.Weekday = ptzi->DaylightDate.wDayOfWeek ;
  1305. DaylightStart.Day = ptzi->DaylightDate.wDay ;
  1306. DaylightStart.Hour = ptzi->DaylightDate.wHour ;
  1307. DaylightStart.Minute = ptzi->DaylightDate.wMinute ;
  1308. DaylightStart.Second = ptzi->DaylightDate.wSecond ;
  1309. DaylightStart.Milliseconds = ptzi->DaylightDate.wMilliseconds;
  1310. //
  1311. // We have timezone cutover information. Compute the
  1312. // cutover dates and compute what our current bias
  1313. // is
  1314. //
  1315. if((!RtlCutoverTimeToSystemTime(&StandardStart,&StandardTime,
  1316. &CurrentUniversalTime,TRUE)) ||
  1317. (!RtlCutoverTimeToSystemTime(&DaylightStart,&DaylightTime,
  1318. &CurrentUniversalTime,TRUE))) {
  1319. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  1320. return TIME_ZONE_ID_INVALID;
  1321. }
  1322. //
  1323. // Convert standard time and daylight time to utc
  1324. //
  1325. LocalCustomBias.QuadPart = Int32x32To64(ptzi->StandardBias*60, 10000000);
  1326. TimeZoneBias.QuadPart = NewTimeZoneBias.QuadPart + LocalCustomBias.QuadPart;
  1327. UtcDaylightTime.QuadPart = DaylightTime.QuadPart + TimeZoneBias.QuadPart;
  1328. LocalCustomBias.QuadPart = Int32x32To64(ptzi->DaylightBias*60, 10000000);
  1329. TimeZoneBias.QuadPart = NewTimeZoneBias.QuadPart + LocalCustomBias.QuadPart;
  1330. UtcStandardTime.QuadPart = StandardTime.QuadPart + TimeZoneBias.QuadPart;
  1331. //
  1332. // If daylight < standard, then time >= daylight and
  1333. // less than standard is daylight
  1334. //
  1335. if ( UtcDaylightTime.QuadPart < UtcStandardTime.QuadPart ) {
  1336. //
  1337. // If today is >= DaylightTime and < StandardTime, then
  1338. // We are in daylight savings time
  1339. //
  1340. if ( (CurrentUniversalTime.QuadPart >= UtcDaylightTime.QuadPart) &&
  1341. (CurrentUniversalTime.QuadPart < UtcStandardTime.QuadPart) ) {
  1342. CurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT;
  1343. } else {
  1344. CurrentTimeZoneId = TIME_ZONE_ID_STANDARD;
  1345. }
  1346. } else {
  1347. //
  1348. // If today is >= StandardTime and < DaylightTime, then
  1349. // We are in standard time
  1350. //
  1351. if ( (CurrentUniversalTime.QuadPart >= UtcStandardTime.QuadPart ) &&
  1352. (CurrentUniversalTime.QuadPart < UtcDaylightTime.QuadPart ) ) {
  1353. CurrentTimeZoneId = TIME_ZONE_ID_STANDARD;
  1354. } else {
  1355. CurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT;
  1356. }
  1357. }
  1358. //
  1359. // At this point, we know our current timezone and the
  1360. // Universal time of the next cutover.
  1361. //
  1362. LocalCustomBias.QuadPart = Int32x32To64(
  1363. CurrentTimeZoneId == TIME_ZONE_ID_DAYLIGHT ?
  1364. ptzi->DaylightBias*60 :
  1365. ptzi->StandardBias*60, // Bias in seconds
  1366. 10000000
  1367. );
  1368. TimeZoneBias.QuadPart = NewTimeZoneBias.QuadPart + LocalCustomBias.QuadPart;
  1369. } else {
  1370. TimeZoneBias = NewTimeZoneBias;
  1371. CurrentTimeZoneId=TIME_ZONE_ID_UNKNOWN;
  1372. }
  1373. pBias->LowPart=(ULONG)(TimeZoneBias.LowPart);
  1374. pBias->High1Time=pBias->High2Time=(LONG)(TimeZoneBias.HighPart);
  1375. return CurrentTimeZoneId;
  1376. }
  1377. BOOL
  1378. IsTimeZoneRedirectionEnabled()
  1379. {
  1380. /*++
  1381. Routine Description:
  1382. Checks if all conditions are met to allow Time Zone redirection
  1383. on the TS session.
  1384. Arguments:
  1385. NONE
  1386. Return Value:
  1387. TRUE - if we allowed to do TZ redirection.
  1388. --*/
  1389. return (BaseStaticServerData->TermsrvClientTimeZoneId != TIME_ZONE_ID_INVALID);
  1390. }
  1391. /*
  1392. //These 2 functions will be needed for new timedate.cpl
  1393. DWORD
  1394. WINAPI
  1395. GetServerTimeZoneInformation(
  1396. LPTIME_ZONE_INFORMATION lpTimeZoneInformation
  1397. )
  1398. {
  1399. RTL_TIME_ZONE_INFORMATION tzi;
  1400. NTSTATUS Status;
  1401. //
  1402. // get the timezone data from the system
  1403. //
  1404. Status = NtQuerySystemInformation(
  1405. SystemCurrentTimeZoneInformation,
  1406. &tzi,
  1407. sizeof(tzi),
  1408. NULL
  1409. );
  1410. if ( !NT_SUCCESS(Status) ) {
  1411. BaseSetLastNTError(Status);
  1412. return 0xffffffff;
  1413. }
  1414. lpTimeZoneInformation->Bias = tzi.Bias;
  1415. lpTimeZoneInformation->StandardBias = tzi.StandardBias;
  1416. lpTimeZoneInformation->DaylightBias = tzi.DaylightBias;
  1417. RtlCopyMemory(&lpTimeZoneInformation->StandardName,&tzi.StandardName,sizeof(tzi.StandardName));
  1418. RtlCopyMemory(&lpTimeZoneInformation->DaylightName,&tzi.DaylightName,sizeof(tzi.DaylightName));
  1419. lpTimeZoneInformation->StandardDate.wYear = tzi.StandardStart.Year ;
  1420. lpTimeZoneInformation->StandardDate.wMonth = tzi.StandardStart.Month ;
  1421. lpTimeZoneInformation->StandardDate.wDayOfWeek = tzi.StandardStart.Weekday ;
  1422. lpTimeZoneInformation->StandardDate.wDay = tzi.StandardStart.Day ;
  1423. lpTimeZoneInformation->StandardDate.wHour = tzi.StandardStart.Hour ;
  1424. lpTimeZoneInformation->StandardDate.wMinute = tzi.StandardStart.Minute ;
  1425. lpTimeZoneInformation->StandardDate.wSecond = tzi.StandardStart.Second ;
  1426. lpTimeZoneInformation->StandardDate.wMilliseconds = tzi.StandardStart.Milliseconds;
  1427. lpTimeZoneInformation->DaylightDate.wYear = tzi.DaylightStart.Year ;
  1428. lpTimeZoneInformation->DaylightDate.wMonth = tzi.DaylightStart.Month ;
  1429. lpTimeZoneInformation->DaylightDate.wDayOfWeek = tzi.DaylightStart.Weekday ;
  1430. lpTimeZoneInformation->DaylightDate.wDay = tzi.DaylightStart.Day ;
  1431. lpTimeZoneInformation->DaylightDate.wHour = tzi.DaylightStart.Hour ;
  1432. lpTimeZoneInformation->DaylightDate.wMinute = tzi.DaylightStart.Minute ;
  1433. lpTimeZoneInformation->DaylightDate.wSecond = tzi.DaylightStart.Second ;
  1434. lpTimeZoneInformation->DaylightDate.wMilliseconds = tzi.DaylightStart.Milliseconds;
  1435. return USER_SHARED_DATA->TimeZoneId;
  1436. }
  1437. BOOL
  1438. WINAPI
  1439. SetServerTimeZoneInformation(
  1440. CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation
  1441. )
  1442. {
  1443. RTL_TIME_ZONE_INFORMATION tzi;
  1444. NTSTATUS Status;
  1445. tzi.Bias = lpTimeZoneInformation->Bias;
  1446. tzi.StandardBias = lpTimeZoneInformation->StandardBias;
  1447. tzi.DaylightBias = lpTimeZoneInformation->DaylightBias;
  1448. RtlCopyMemory(&tzi.StandardName,&lpTimeZoneInformation->StandardName,sizeof(tzi.StandardName));
  1449. RtlCopyMemory(&tzi.DaylightName,&lpTimeZoneInformation->DaylightName,sizeof(tzi.DaylightName));
  1450. tzi.StandardStart.Year = lpTimeZoneInformation->StandardDate.wYear ;
  1451. tzi.StandardStart.Month = lpTimeZoneInformation->StandardDate.wMonth ;
  1452. tzi.StandardStart.Weekday = lpTimeZoneInformation->StandardDate.wDayOfWeek ;
  1453. tzi.StandardStart.Day = lpTimeZoneInformation->StandardDate.wDay ;
  1454. tzi.StandardStart.Hour = lpTimeZoneInformation->StandardDate.wHour ;
  1455. tzi.StandardStart.Minute = lpTimeZoneInformation->StandardDate.wMinute ;
  1456. tzi.StandardStart.Second = lpTimeZoneInformation->StandardDate.wSecond ;
  1457. tzi.StandardStart.Milliseconds = lpTimeZoneInformation->StandardDate.wMilliseconds;
  1458. tzi.DaylightStart.Year = lpTimeZoneInformation->DaylightDate.wYear ;
  1459. tzi.DaylightStart.Month = lpTimeZoneInformation->DaylightDate.wMonth ;
  1460. tzi.DaylightStart.Weekday = lpTimeZoneInformation->DaylightDate.wDayOfWeek ;
  1461. tzi.DaylightStart.Day = lpTimeZoneInformation->DaylightDate.wDay ;
  1462. tzi.DaylightStart.Hour = lpTimeZoneInformation->DaylightDate.wHour ;
  1463. tzi.DaylightStart.Minute = lpTimeZoneInformation->DaylightDate.wMinute ;
  1464. tzi.DaylightStart.Second = lpTimeZoneInformation->DaylightDate.wSecond ;
  1465. tzi.DaylightStart.Milliseconds = lpTimeZoneInformation->DaylightDate.wMilliseconds;
  1466. Status = RtlSetTimeZoneInformation( &tzi );
  1467. if (!NT_SUCCESS( Status )) {
  1468. BaseSetLastNTError(Status);
  1469. return FALSE;
  1470. }
  1471. //
  1472. // Refresh the system's concept of time
  1473. //
  1474. NtSetSystemTime(NULL,NULL);
  1475. return TRUE;
  1476. }
  1477. */