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 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 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 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 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 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 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