2 * Unit test suite for ntdll time functions
4 * Copyright 2004 Rein Klazes
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.
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.
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
21 #define NONAMELESSUNION
22 #include "ntdll_test.h"
26 typedef struct _KSYSTEM_TIME
{
30 } KSYSTEM_TIME
, *PKSYSTEM_TIME
;
32 typedef enum _NT_PRODUCT_TYPE
{
36 } NT_PRODUCT_TYPE
, *PNT_PRODUCT_TYPE
;
38 #define PROCESSOR_FEATURE_MAX 64
40 typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE
45 } ALTERNATIVE_ARCHITECTURE_TYPE
;
47 #define MAX_WOW64_SHARED_ENTRIES 16
49 typedef struct _KUSER_SHARED_DATA
{
50 ULONG TickCountLowDeprecated
;
51 ULONG TickCountMultiplier
;
52 volatile KSYSTEM_TIME InterruptTime
;
53 volatile KSYSTEM_TIME SystemTime
;
54 volatile KSYSTEM_TIME TimeZoneBias
;
55 USHORT ImageNumberLow
;
56 USHORT ImageNumberHigh
;
57 WCHAR NtSystemRoot
[260];
58 ULONG MaxStackTraceDepth
;
61 ULONG LargePageMinimum
;
63 NT_PRODUCT_TYPE NtProductType
;
64 BOOLEAN ProductTypeIsValid
;
67 BOOLEAN ProcessorFeatures
[PROCESSOR_FEATURE_MAX
];
70 volatile ULONG TimeSlip
;
71 ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture
;
72 LARGE_INTEGER SystemExpirationDate
;
74 BOOLEAN KdDebuggerEnabled
;
75 UCHAR NXSupportPolicy
;
76 volatile ULONG ActiveConsoleId
;
77 volatile ULONG DismountCount
;
79 ULONG LastSystemRITEventTickCount
;
80 ULONG NumberOfPhysicalPages
;
83 ULONGLONG TestRetInstruction
;
85 ULONG SystemCallReturn
;
86 ULONGLONG SystemCallPad
[3];
88 volatile KSYSTEM_TIME TickCount
;
89 volatile ULONG64 TickCountQuad
;
92 ULONG Wow64SharedInformation
[MAX_WOW64_SHARED_ENTRIES
];
93 } KSHARED_USER_DATA
, *PKSHARED_USER_DATA
;
95 #define TICKSPERSEC 10000000
96 #define TICKSPERMSEC 10000
97 #define SECSPERDAY 86400
99 static VOID (WINAPI
*pRtlTimeToTimeFields
)( const LARGE_INTEGER
*liTime
, PTIME_FIELDS TimeFields
) ;
100 static VOID (WINAPI
*pRtlTimeFieldsToTime
)( PTIME_FIELDS TimeFields
, PLARGE_INTEGER Time
) ;
101 static NTSTATUS (WINAPI
*pNtQueryPerformanceCounter
)( LARGE_INTEGER
*counter
, LARGE_INTEGER
*frequency
);
102 static ULONG (WINAPI
*pNtGetTickCount
)(void);
104 static const int MonthLengths
[2][12] =
106 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
107 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
110 static inline BOOL
IsLeapYear(int Year
)
112 return Year
% 4 == 0 && (Year
% 100 != 0 || Year
% 400 == 0);
115 /* start time of the tests */
116 static TIME_FIELDS tftest
= {1889,12,31,23,59,59,0,0};
118 static void test_pRtlTimeToTimeFields(void)
120 LARGE_INTEGER litime
, liresult
;
121 TIME_FIELDS tfresult
;
123 litime
.QuadPart
= ((ULONGLONG
)0x0144017a << 32) | 0xf0b0a980;
124 while( tftest
.Year
< 2110 ) {
125 /* test at the last second of the month */
126 pRtlTimeToTimeFields( &litime
, &tfresult
);
127 ok( tfresult
.Year
== tftest
.Year
&& tfresult
.Month
== tftest
.Month
&&
128 tfresult
.Day
== tftest
.Day
&& tfresult
.Hour
== tftest
.Hour
&&
129 tfresult
.Minute
== tftest
.Minute
&& tfresult
.Second
== tftest
.Second
,
130 "#%d expected: %d-%d-%d %d:%d:%d got: %d-%d-%d %d:%d:%d\n", ++i
,
131 tftest
.Year
, tftest
.Month
, tftest
.Day
,
132 tftest
.Hour
, tftest
.Minute
,tftest
.Second
,
133 tfresult
.Year
, tfresult
.Month
, tfresult
.Day
,
134 tfresult
.Hour
, tfresult
.Minute
, tfresult
.Second
);
135 /* test the inverse */
136 pRtlTimeFieldsToTime( &tfresult
, &liresult
);
137 ok( liresult
.QuadPart
== litime
.QuadPart
," TimeFieldsToTime failed on %d-%d-%d %d:%d:%d. Error is %d ticks\n",
138 tfresult
.Year
, tfresult
.Month
, tfresult
.Day
,
139 tfresult
.Hour
, tfresult
.Minute
, tfresult
.Second
,
140 (int) (liresult
.QuadPart
- litime
.QuadPart
) );
141 /* one second later is beginning of next month */
142 litime
.QuadPart
+= TICKSPERSEC
;
143 pRtlTimeToTimeFields( &litime
, &tfresult
);
144 ok( tfresult
.Year
== tftest
.Year
+ (tftest
.Month
==12) &&
145 tfresult
.Month
== tftest
.Month
% 12 + 1 &&
146 tfresult
.Day
== 1 && tfresult
.Hour
== 0 &&
147 tfresult
.Minute
== 0 && tfresult
.Second
== 0,
148 "#%d expected: %d-%d-%d %d:%d:%d got: %d-%d-%d %d:%d:%d\n", ++i
,
149 tftest
.Year
+ (tftest
.Month
==12),
150 tftest
.Month
% 12 + 1, 1, 0, 0, 0,
151 tfresult
.Year
, tfresult
.Month
, tfresult
.Day
,
152 tfresult
.Hour
, tfresult
.Minute
, tfresult
.Second
);
153 /* test the inverse */
154 pRtlTimeFieldsToTime( &tfresult
, &liresult
);
155 ok( liresult
.QuadPart
== litime
.QuadPart
," TimeFieldsToTime failed on %d-%d-%d %d:%d:%d. Error is %d ticks\n",
156 tfresult
.Year
, tfresult
.Month
, tfresult
.Day
,
157 tfresult
.Hour
, tfresult
.Minute
, tfresult
.Second
,
158 (int) (liresult
.QuadPart
- litime
.QuadPart
) );
159 /* advance to the end of the month */
160 litime
.QuadPart
-= TICKSPERSEC
;
161 if( tftest
.Month
== 12) {
166 tftest
.Day
= MonthLengths
[IsLeapYear(tftest
.Year
)][tftest
.Month
- 1];
167 litime
.QuadPart
+= (LONGLONG
) tftest
.Day
* TICKSPERSEC
* SECSPERDAY
;
171 static void test_NtQueryPerformanceCounter(void)
173 LARGE_INTEGER counter
, frequency
;
176 status
= pNtQueryPerformanceCounter(NULL
, NULL
);
177 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status
);
178 status
= pNtQueryPerformanceCounter(NULL
, &frequency
);
179 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status
);
180 status
= pNtQueryPerformanceCounter(&counter
, (void *)0xdeadbee0);
181 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status
);
182 status
= pNtQueryPerformanceCounter((void *)0xdeadbee0, &frequency
);
183 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status
);
185 status
= pNtQueryPerformanceCounter(&counter
, NULL
);
186 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
187 status
= pNtQueryPerformanceCounter(&counter
, &frequency
);
188 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
191 static void test_NtGetTickCount(void)
194 KSHARED_USER_DATA
*user_shared_data
= (void *)0x7ffe0000;
198 if (!pNtGetTickCount
)
200 win_skip("NtGetTickCount is not available\n");
204 for (i
= 0; i
< 5; ++i
)
206 diff
= (user_shared_data
->u
.TickCountQuad
* user_shared_data
->TickCountMultiplier
) >> 24;
207 diff
= pNtGetTickCount() - diff
;
208 ok(diff
< 32, "NtGetTickCount - TickCountQuad too high, expected < 32 got %d\n", diff
);
216 HMODULE mod
= GetModuleHandleA("ntdll.dll");
217 pRtlTimeToTimeFields
= (void *)GetProcAddress(mod
,"RtlTimeToTimeFields");
218 pRtlTimeFieldsToTime
= (void *)GetProcAddress(mod
,"RtlTimeFieldsToTime");
219 pNtQueryPerformanceCounter
= (void *)GetProcAddress(mod
, "NtQueryPerformanceCounter");
220 pNtGetTickCount
= (void *)GetProcAddress(mod
,"NtGetTickCount");
221 if (pRtlTimeToTimeFields
&& pRtlTimeFieldsToTime
)
222 test_pRtlTimeToTimeFields();
224 win_skip("Required time conversion functions are not available\n");
225 test_NtQueryPerformanceCounter();
226 test_NtGetTickCount();