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 #include "ntdll_test.h"
25 typedef struct _KSYSTEM_TIME
{
29 } KSYSTEM_TIME
, *PKSYSTEM_TIME
;
31 typedef enum _NT_PRODUCT_TYPE
{
35 } NT_PRODUCT_TYPE
, *PNT_PRODUCT_TYPE
;
37 #define PROCESSOR_FEATURE_MAX 64
39 typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE
44 } ALTERNATIVE_ARCHITECTURE_TYPE
;
46 #define MAX_WOW64_SHARED_ENTRIES 16
48 typedef struct _KUSER_SHARED_DATA
{
49 ULONG TickCountLowDeprecated
;
50 ULONG TickCountMultiplier
;
51 volatile KSYSTEM_TIME InterruptTime
;
52 volatile KSYSTEM_TIME SystemTime
;
53 volatile KSYSTEM_TIME TimeZoneBias
;
54 USHORT ImageNumberLow
;
55 USHORT ImageNumberHigh
;
56 WCHAR NtSystemRoot
[260];
57 ULONG MaxStackTraceDepth
;
60 ULONG LargePageMinimum
;
62 NT_PRODUCT_TYPE NtProductType
;
63 BOOLEAN ProductTypeIsValid
;
66 BOOLEAN ProcessorFeatures
[PROCESSOR_FEATURE_MAX
];
69 volatile ULONG TimeSlip
;
70 ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture
;
71 LARGE_INTEGER SystemExpirationDate
;
73 BOOLEAN KdDebuggerEnabled
;
74 UCHAR NXSupportPolicy
;
75 volatile ULONG ActiveConsoleId
;
76 volatile ULONG DismountCount
;
78 ULONG LastSystemRITEventTickCount
;
79 ULONG NumberOfPhysicalPages
;
82 ULONGLONG TestRetInstruction
;
84 ULONG SystemCallReturn
;
85 ULONGLONG SystemCallPad
[3];
87 volatile KSYSTEM_TIME TickCount
;
88 volatile ULONG64 TickCountQuad
;
91 ULONG Wow64SharedInformation
[MAX_WOW64_SHARED_ENTRIES
];
92 } KSHARED_USER_DATA
, *PKSHARED_USER_DATA
;
94 #define TICKSPERSEC 10000000
95 #define TICKSPERMSEC 10000
96 #define SECSPERDAY 86400
98 static VOID (WINAPI
*pRtlTimeToTimeFields
)( const LARGE_INTEGER
*liTime
, PTIME_FIELDS TimeFields
) ;
99 static VOID (WINAPI
*pRtlTimeFieldsToTime
)( PTIME_FIELDS TimeFields
, PLARGE_INTEGER Time
) ;
100 static NTSTATUS (WINAPI
*pNtQueryPerformanceCounter
)( LARGE_INTEGER
*counter
, LARGE_INTEGER
*frequency
);
101 static ULONG (WINAPI
*pNtGetTickCount
)(void);
103 static const int MonthLengths
[2][12] =
105 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
106 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
109 static inline BOOL
IsLeapYear(int Year
)
111 return Year
% 4 == 0 && (Year
% 100 != 0 || Year
% 400 == 0);
114 /* start time of the tests */
115 static TIME_FIELDS tftest
= {1889,12,31,23,59,59,0,0};
117 static void test_pRtlTimeToTimeFields(void)
119 LARGE_INTEGER litime
, liresult
;
120 TIME_FIELDS tfresult
;
122 litime
.QuadPart
= ((ULONGLONG
)0x0144017a << 32) | 0xf0b0a980;
123 while( tftest
.Year
< 2110 ) {
124 /* test at the last second of the month */
125 pRtlTimeToTimeFields( &litime
, &tfresult
);
126 ok( tfresult
.Year
== tftest
.Year
&& tfresult
.Month
== tftest
.Month
&&
127 tfresult
.Day
== tftest
.Day
&& tfresult
.Hour
== tftest
.Hour
&&
128 tfresult
.Minute
== tftest
.Minute
&& tfresult
.Second
== tftest
.Second
,
129 "#%d expected: %d-%d-%d %d:%d:%d got: %d-%d-%d %d:%d:%d\n", ++i
,
130 tftest
.Year
, tftest
.Month
, tftest
.Day
,
131 tftest
.Hour
, tftest
.Minute
,tftest
.Second
,
132 tfresult
.Year
, tfresult
.Month
, tfresult
.Day
,
133 tfresult
.Hour
, tfresult
.Minute
, tfresult
.Second
);
134 /* test the inverse */
135 pRtlTimeFieldsToTime( &tfresult
, &liresult
);
136 ok( liresult
.QuadPart
== litime
.QuadPart
," TimeFieldsToTime failed on %d-%d-%d %d:%d:%d. Error is %d ticks\n",
137 tfresult
.Year
, tfresult
.Month
, tfresult
.Day
,
138 tfresult
.Hour
, tfresult
.Minute
, tfresult
.Second
,
139 (int) (liresult
.QuadPart
- litime
.QuadPart
) );
140 /* one second later is beginning of next month */
141 litime
.QuadPart
+= TICKSPERSEC
;
142 pRtlTimeToTimeFields( &litime
, &tfresult
);
143 ok( tfresult
.Year
== tftest
.Year
+ (tftest
.Month
==12) &&
144 tfresult
.Month
== tftest
.Month
% 12 + 1 &&
145 tfresult
.Day
== 1 && tfresult
.Hour
== 0 &&
146 tfresult
.Minute
== 0 && tfresult
.Second
== 0,
147 "#%d expected: %d-%d-%d %d:%d:%d got: %d-%d-%d %d:%d:%d\n", ++i
,
148 tftest
.Year
+ (tftest
.Month
==12),
149 tftest
.Month
% 12 + 1, 1, 0, 0, 0,
150 tfresult
.Year
, tfresult
.Month
, tfresult
.Day
,
151 tfresult
.Hour
, tfresult
.Minute
, tfresult
.Second
);
152 /* test the inverse */
153 pRtlTimeFieldsToTime( &tfresult
, &liresult
);
154 ok( liresult
.QuadPart
== litime
.QuadPart
," TimeFieldsToTime failed on %d-%d-%d %d:%d:%d. Error is %d ticks\n",
155 tfresult
.Year
, tfresult
.Month
, tfresult
.Day
,
156 tfresult
.Hour
, tfresult
.Minute
, tfresult
.Second
,
157 (int) (liresult
.QuadPart
- litime
.QuadPart
) );
158 /* advance to the end of the month */
159 litime
.QuadPart
-= TICKSPERSEC
;
160 if( tftest
.Month
== 12) {
165 tftest
.Day
= MonthLengths
[IsLeapYear(tftest
.Year
)][tftest
.Month
- 1];
166 litime
.QuadPart
+= (LONGLONG
) tftest
.Day
* TICKSPERSEC
* SECSPERDAY
;
170 static void test_NtQueryPerformanceCounter(void)
172 LARGE_INTEGER counter
, frequency
;
175 status
= pNtQueryPerformanceCounter(NULL
, NULL
);
176 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status
);
177 status
= pNtQueryPerformanceCounter(NULL
, &frequency
);
178 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status
);
179 status
= pNtQueryPerformanceCounter(&counter
, (void *)0xdeadbee0);
180 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status
);
181 status
= pNtQueryPerformanceCounter((void *)0xdeadbee0, &frequency
);
182 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status
);
184 status
= pNtQueryPerformanceCounter(&counter
, NULL
);
185 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
186 status
= pNtQueryPerformanceCounter(&counter
, &frequency
);
187 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
190 static void test_NtGetTickCount(void)
193 KSHARED_USER_DATA
*user_shared_data
= (void *)0x7ffe0000;
197 if (!pNtGetTickCount
)
199 win_skip("NtGetTickCount is not available\n");
203 for (i
= 0; i
< 5; ++i
)
205 diff
= (user_shared_data
->TickCountQuad
* user_shared_data
->TickCountMultiplier
) >> 24;
206 diff
= pNtGetTickCount() - diff
;
207 ok(diff
< 32, "NtGetTickCount - TickCountQuad too high, expected < 32 got %d\n", diff
);
215 HMODULE mod
= GetModuleHandleA("ntdll.dll");
216 pRtlTimeToTimeFields
= (void *)GetProcAddress(mod
,"RtlTimeToTimeFields");
217 pRtlTimeFieldsToTime
= (void *)GetProcAddress(mod
,"RtlTimeFieldsToTime");
218 pNtQueryPerformanceCounter
= (void *)GetProcAddress(mod
, "NtQueryPerformanceCounter");
219 pNtGetTickCount
= (void *)GetProcAddress(mod
,"NtGetTickCount");
220 if (pRtlTimeToTimeFields
&& pRtlTimeFieldsToTime
)
221 test_pRtlTimeToTimeFields();
223 win_skip("Required time conversion functions are not available\n");
224 test_NtQueryPerformanceCounter();
225 test_NtGetTickCount();