1 /*
2 * Unit test suite for ntdll time functions
3 *
4 * Copyright 2004 Rein Klazes
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #ifndef __REACTOS__
22 #define NONAMELESSUNION
23 #endif
24 #include "ntdll_test.h"
25 #ifndef __REACTOS__
26 #include "ddk/wdm.h"
27 #else /* FIXME: Inspect */
28
29 typedef struct _KSYSTEM_TIME {
30 ULONG LowPart;
31 LONG High1Time;
32 LONG High2Time;
33 } KSYSTEM_TIME, *PKSYSTEM_TIME;
34
35 typedef enum _NT_PRODUCT_TYPE {
36 NtProductWinNt = 1,
37 NtProductLanManNt,
38 NtProductServer
39 } NT_PRODUCT_TYPE, *PNT_PRODUCT_TYPE;
40
41 #define PROCESSOR_FEATURE_MAX 64
42
43 typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE
44 {
45 StandardDesign,
46 NEC98x86,
47 EndAlternatives
48 } ALTERNATIVE_ARCHITECTURE_TYPE;
49
50 #define MAX_WOW64_SHARED_ENTRIES 16
51
52 typedef struct _KUSER_SHARED_DATA {
53 ULONG TickCountLowDeprecated;
54 ULONG TickCountMultiplier;
55 volatile KSYSTEM_TIME InterruptTime;
56 volatile KSYSTEM_TIME SystemTime;
57 volatile KSYSTEM_TIME TimeZoneBias;
58 USHORT ImageNumberLow;
59 USHORT ImageNumberHigh;
60 WCHAR NtSystemRoot[260];
61 ULONG MaxStackTraceDepth;
62 ULONG CryptoExponent;
63 ULONG TimeZoneId;
64 ULONG LargePageMinimum;
65 ULONG Reserved2[7];
66 NT_PRODUCT_TYPE NtProductType;
67 BOOLEAN ProductTypeIsValid;
68 ULONG NtMajorVersion;
69 ULONG NtMinorVersion;
70 BOOLEAN ProcessorFeatures[PROCESSOR_FEATURE_MAX];
71 ULONG Reserved1;
72 ULONG Reserved3;
73 volatile ULONG TimeSlip;
74 ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture;
75 LARGE_INTEGER SystemExpirationDate;
76 ULONG SuiteMask;
77 BOOLEAN KdDebuggerEnabled;
78 UCHAR NXSupportPolicy;
79 volatile ULONG ActiveConsoleId;
80 volatile ULONG DismountCount;
81 ULONG ComPlusPackage;
82 ULONG LastSystemRITEventTickCount;
83 ULONG NumberOfPhysicalPages;
84 BOOLEAN SafeBootMode;
85 ULONG TraceLogging;
86 ULONGLONG TestRetInstruction;
87 ULONG SystemCall;
88 ULONG SystemCallReturn;
89 ULONGLONG SystemCallPad[3];
90 union {
91 volatile KSYSTEM_TIME TickCount;
92 volatile ULONG64 TickCountQuad;
93 } DUMMYUNIONNAME;
94 ULONG Cookie;
95 ULONG Wow64SharedInformation[MAX_WOW64_SHARED_ENTRIES];
96 } KSHARED_USER_DATA, *PKSHARED_USER_DATA;
97
98 #endif /* !__REACTOS__ */
99
100 #define TICKSPERSEC 10000000
101 #define TICKSPERMSEC 10000
102 #define SECSPERDAY 86400
103
104 static VOID (WINAPI *pRtlTimeToTimeFields)( const LARGE_INTEGER *liTime, PTIME_FIELDS TimeFields) ;
105 static VOID (WINAPI *pRtlTimeFieldsToTime)( PTIME_FIELDS TimeFields, PLARGE_INTEGER Time) ;
106 static NTSTATUS (WINAPI *pNtQueryPerformanceCounter)( LARGE_INTEGER *counter, LARGE_INTEGER *frequency );
107 static NTSTATUS (WINAPI *pRtlQueryTimeZoneInformation)( RTL_TIME_ZONE_INFORMATION *);
108 static NTSTATUS (WINAPI *pRtlQueryDynamicTimeZoneInformation)( RTL_DYNAMIC_TIME_ZONE_INFORMATION *);
109 static ULONG (WINAPI *pNtGetTickCount)(void);
110
111 static const int MonthLengths[2][12] =
112 {
113 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
114 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
115 };
116
IsLeapYear(int Year)117 static inline BOOL IsLeapYear(int Year)
118 {
119 return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0);
120 }
121
122 /* start time of the tests */
123 static TIME_FIELDS tftest = {1889,12,31,23,59,59,0,0};
124
test_pRtlTimeToTimeFields(void)125 static void test_pRtlTimeToTimeFields(void)
126 {
127 LARGE_INTEGER litime , liresult;
128 TIME_FIELDS tfresult;
129 int i=0;
130 litime.QuadPart = ((ULONGLONG)0x0144017a << 32) | 0xf0b0a980;
131 while( tftest.Year < 2110 ) {
132 /* test at the last second of the month */
133 pRtlTimeToTimeFields( &litime, &tfresult);
134 ok( tfresult.Year == tftest.Year && tfresult.Month == tftest.Month &&
135 tfresult.Day == tftest.Day && tfresult.Hour == tftest.Hour &&
136 tfresult.Minute == tftest.Minute && tfresult.Second == tftest.Second,
137 "#%d expected: %d-%d-%d %d:%d:%d got: %d-%d-%d %d:%d:%d\n", ++i,
138 tftest.Year, tftest.Month, tftest.Day,
139 tftest.Hour, tftest.Minute,tftest.Second,
140 tfresult.Year, tfresult.Month, tfresult.Day,
141 tfresult.Hour, tfresult.Minute, tfresult.Second);
142 /* test the inverse */
143 pRtlTimeFieldsToTime( &tfresult, &liresult);
144 ok( liresult.QuadPart == litime.QuadPart," TimeFieldsToTime failed on %d-%d-%d %d:%d:%d. Error is %d ticks\n",
145 tfresult.Year, tfresult.Month, tfresult.Day,
146 tfresult.Hour, tfresult.Minute, tfresult.Second,
147 (int) (liresult.QuadPart - litime.QuadPart) );
148 /* one second later is beginning of next month */
149 litime.QuadPart += TICKSPERSEC ;
150 pRtlTimeToTimeFields( &litime, &tfresult);
151 ok( tfresult.Year == tftest.Year + (tftest.Month ==12) &&
152 tfresult.Month == tftest.Month % 12 + 1 &&
153 tfresult.Day == 1 && tfresult.Hour == 0 &&
154 tfresult.Minute == 0 && tfresult.Second == 0,
155 "#%d expected: %d-%d-%d %d:%d:%d got: %d-%d-%d %d:%d:%d\n", ++i,
156 tftest.Year + (tftest.Month ==12),
157 tftest.Month % 12 + 1, 1, 0, 0, 0,
158 tfresult.Year, tfresult.Month, tfresult.Day,
159 tfresult.Hour, tfresult.Minute, tfresult.Second);
160 /* test the inverse */
161 pRtlTimeFieldsToTime( &tfresult, &liresult);
162 ok( liresult.QuadPart == litime.QuadPart," TimeFieldsToTime failed on %d-%d-%d %d:%d:%d. Error is %d ticks\n",
163 tfresult.Year, tfresult.Month, tfresult.Day,
164 tfresult.Hour, tfresult.Minute, tfresult.Second,
165 (int) (liresult.QuadPart - litime.QuadPart) );
166 /* advance to the end of the month */
167 litime.QuadPart -= TICKSPERSEC ;
168 if( tftest.Month == 12) {
169 tftest.Month = 1;
170 tftest.Year += 1;
171 } else
172 tftest.Month += 1;
173 tftest.Day = MonthLengths[IsLeapYear(tftest.Year)][tftest.Month - 1];
174 litime.QuadPart += (LONGLONG) tftest.Day * TICKSPERSEC * SECSPERDAY;
175 }
176 }
177
test_NtQueryPerformanceCounter(void)178 static void test_NtQueryPerformanceCounter(void)
179 {
180 LARGE_INTEGER counter, frequency;
181 NTSTATUS status;
182
183 status = pNtQueryPerformanceCounter(NULL, NULL);
184 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
185 status = pNtQueryPerformanceCounter(NULL, &frequency);
186 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
187 status = pNtQueryPerformanceCounter(&counter, (void *)0xdeadbee0);
188 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
189 status = pNtQueryPerformanceCounter((void *)0xdeadbee0, &frequency);
190 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
191
192 status = pNtQueryPerformanceCounter(&counter, NULL);
193 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
194 status = pNtQueryPerformanceCounter(&counter, &frequency);
195 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
196 }
197
test_RtlQueryTimeZoneInformation(void)198 static void test_RtlQueryTimeZoneInformation(void)
199 {
200 RTL_DYNAMIC_TIME_ZONE_INFORMATION tzinfo;
201 NTSTATUS status;
202
203 /* test RtlQueryTimeZoneInformation returns an indirect string,
204 e.g. @tzres.dll,-32 (Vista or later) */
205 if (!pRtlQueryTimeZoneInformation || !pRtlQueryDynamicTimeZoneInformation)
206 {
207 win_skip("Time zone name tests requires Vista or later\n");
208 return;
209 }
210
211 memset(&tzinfo, 0, sizeof(tzinfo));
212 status = pRtlQueryDynamicTimeZoneInformation(&tzinfo);
213 ok(status == STATUS_SUCCESS,
214 "RtlQueryDynamicTimeZoneInformation failed, got %08x\n", status);
215 todo_wine ok(tzinfo.StandardName[0] == '@',
216 "standard time zone name isn't an indirect string, got %s\n",
217 wine_dbgstr_w(tzinfo.StandardName));
218 todo_wine ok(tzinfo.DaylightName[0] == '@',
219 "daylight time zone name isn't an indirect string, got %s\n",
220 wine_dbgstr_w(tzinfo.DaylightName));
221
222 memset(&tzinfo, 0, sizeof(tzinfo));
223 status = pRtlQueryTimeZoneInformation((RTL_TIME_ZONE_INFORMATION *)&tzinfo);
224 ok(status == STATUS_SUCCESS,
225 "RtlQueryTimeZoneInformation failed, got %08x\n", status);
226 todo_wine ok(tzinfo.StandardName[0] == '@',
227 "standard time zone name isn't an indirect string, got %s\n",
228 wine_dbgstr_w(tzinfo.StandardName));
229 todo_wine ok(tzinfo.DaylightName[0] == '@',
230 "daylight time zone name isn't an indirect string, got %s\n",
231 wine_dbgstr_w(tzinfo.DaylightName));
232 }
233
test_NtGetTickCount(void)234 static void test_NtGetTickCount(void)
235 {
236 #ifndef _WIN64
237 KSHARED_USER_DATA *user_shared_data = (void *)0x7ffe0000;
238 LONG diff;
239 int i;
240
241 if (!pNtGetTickCount)
242 {
243 win_skip("NtGetTickCount is not available\n");
244 return;
245 }
246
247 for (i = 0; i < 5; ++i)
248 {
249 diff = (user_shared_data->TickCountQuad * user_shared_data->TickCountMultiplier) >> 24;
250 diff = pNtGetTickCount() - diff;
251 ok(diff < 32, "NtGetTickCount - TickCountQuad too high, expected < 32 got %d\n", diff);
252 Sleep(50);
253 }
254 #endif
255 }
256
START_TEST(time)257 START_TEST(time)
258 {
259 HMODULE mod = GetModuleHandleA("ntdll.dll");
260 pRtlTimeToTimeFields = (void *)GetProcAddress(mod,"RtlTimeToTimeFields");
261 pRtlTimeFieldsToTime = (void *)GetProcAddress(mod,"RtlTimeFieldsToTime");
262 pNtQueryPerformanceCounter = (void *)GetProcAddress(mod, "NtQueryPerformanceCounter");
263 pNtGetTickCount = (void *)GetProcAddress(mod,"NtGetTickCount");
264 pRtlQueryTimeZoneInformation =
265 (void *)GetProcAddress(mod, "RtlQueryTimeZoneInformation");
266 pRtlQueryDynamicTimeZoneInformation =
267 (void *)GetProcAddress(mod, "RtlQueryDynamicTimeZoneInformation");
268
269 if (pRtlTimeToTimeFields && pRtlTimeFieldsToTime)
270 test_pRtlTimeToTimeFields();
271 else
272 win_skip("Required time conversion functions are not available\n");
273 test_NtQueryPerformanceCounter();
274 test_NtGetTickCount();
275 test_RtlQueryTimeZoneInformation();
276 }
277