1 /*
2  * PROJECT:     ntdll_apitest
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Tests for RtlQueryTimeZoneInformation
5  * COPYRIGHT:   Copyright 2018 Doug Lyons
6  */
7 
8 #include "precomp.h"
9 
10 #if 0
11 /*
12  * RTL_SYSTEM_TIME is almost the same as the SYSTEMTIME structure defined
13  * in winbase.h, however we need to define it differently here.
14  * This is used by RtlQueryTimeZoneInformation and RtlSetTimeZoneInformation.
15  * See: https://social.msdn.microsoft.com/Forums/en-US/home?forum=en-US and
16  * Search: Reading TimeZone binary data from registry by Patrick
17  *    and then look at the last post showing typedef struct SYSTEMTIME_TZI.
18  */
19 typedef struct _RTL_SYSTEM_TIME {
20     WORD wYear;
21     WORD wMonth;
22     WORD wDay;                  /* wDayOfWeek was here normally */
23     WORD wHour;
24     WORD wMinute;
25     WORD wSecond;
26     WORD wMilliseconds;
27     WORD wDayOfWeek;            /* wDayOfWeek relocated to here */
28 } RTL_SYSTEM_TIME;
29 
30 /*
31  * RTL_TIME_ZONE_INFORMATION is the same as the TIME_ZONE_INFORMATION structure
32  * defined in winbase.h, however we need to define RTL_TIME_ZONE_INFORMATION
33  * seperately here so we don't depend on winbase.h.
34  * This is used by RtlQueryTimeZoneInformation and RtlSetTimeZoneInformation.
35  */
36 typedef struct _RTL_TIME_ZONE_INFORMATION {
37     LONG Bias;
38     WCHAR StandardName[32];
39     RTL_SYSTEM_TIME StandardDate;
40     LONG StandardBias;
41     WCHAR DaylightName[32];
42     RTL_SYSTEM_TIME DaylightDate;
43     LONG DaylightBias;
44 } RTL_TIME_ZONE_INFORMATION;
45 #endif
46 
47 static NTSTATUS (WINAPI *pRtlQueryTimeZoneInformation)( RTL_TIME_ZONE_INFORMATION *);
48 
49 static void test_RtlQueryTimeZoneInformation(void)
50 {
51     RTL_TIME_ZONE_INFORMATION tzinfo;
52     NTSTATUS status;
53     TIME_ZONE_INFORMATION tziOld, tziNew, tziTest;
54     DWORD dwRet;
55 
56     // Retrieve the current time zone information
57 
58     dwRet = GetTimeZoneInformation(&tziOld);
59 
60     ok(dwRet == TIME_ZONE_ID_STANDARD || dwRet == TIME_ZONE_ID_UNKNOWN || dwRet == TIME_ZONE_ID_DAYLIGHT,
61         "Get Time Zone Name failed with error = %ld.\n", GetLastError());
62 
63     // Adjust the time zone information
64 
65     ZeroMemory(&tziNew, sizeof(tziNew));
66     tziNew.Bias = 360;
67     wcscpy(tziNew.StandardName, L"Test Standard Zone");
68     tziNew.StandardDate.wMonth = 11;
69     tziNew.StandardDate.wDayOfWeek = 5;
70     tziNew.StandardDate.wDay = 3;
71     tziNew.StandardDate.wHour = 2;
72     tziNew.StandardBias = 120;
73 
74     wcscpy(tziNew.DaylightName, L"Test Daylight Zone");
75     tziNew.DaylightDate.wMonth = 4;
76     tziNew.DaylightDate.wDayOfWeek = 6;
77     tziNew.DaylightDate.wDay = 2;
78     tziNew.DaylightDate.wHour = 2;
79     tziNew.DaylightBias = -60;
80 
81     // Set up SetLastError with known value for later testing
82 
83     SetLastError(0xDEADBEEF);
84 
85     ok(SetTimeZoneInformation(&tziNew) ,
86         "Set Time Zone Information failed with error = %ld.\n", GetLastError());
87 
88     // if we got an error the function failed, so there is not much else we can do
89 
90     if(GetLastError() != 0xDEADBEEF)
91     {
92         win_skip("SetTimeZoneInformation() is not available, so tests cannot be run.\n");
93         return;
94     }
95 
96     // Retrieve and display the newly set time zone information
97 
98     dwRet = GetTimeZoneInformation(&tziTest);
99 
100     ok(dwRet == TIME_ZONE_ID_STANDARD || dwRet == TIME_ZONE_ID_UNKNOWN || dwRet == TIME_ZONE_ID_DAYLIGHT,
101         "Get Time Zone Information Returned failed with error = %ld.\n", GetLastError());
102 
103     ok(!wcscmp(tziTest.StandardName, tziNew.StandardName),
104         "Standard Time Zone Name = %ls, expected %ls.\n", tziTest.StandardName, tziNew.StandardName);
105 
106     ok(!wcscmp(tziTest.DaylightName, tziNew.DaylightName),
107         "Standard Time Zone Name = %ls, expected %ls.\n", tziTest.DaylightName, tziNew.DaylightName);
108 
109     /* test RtlQueryTimeZoneInformation returns a TIME_ZONE_INFORMATION structure */
110 
111     if (!pRtlQueryTimeZoneInformation)
112     {
113         win_skip("pRtlQueryTimeZoneInformation() fails, so tests cannot be run.\n");
114         return;
115     }
116 
117     /* Clear Time Zone Info field */
118     memset(&tzinfo, 0, sizeof(tzinfo));
119 
120     /* Read Time Zone Info */
121     status = pRtlQueryTimeZoneInformation(&tzinfo);
122     ok(status == STATUS_SUCCESS, "pRtlQueryTimeZoneInformation failed, got %08lx\n", status);
123 
124     /* Check for the Daylight Date Info */
125     ok(tzinfo.DaylightDate.Month == 4, "tzinfo.DaylightDate.wMonth expected '4', got '%d'.\n", tzinfo.DaylightDate.Month);
126     ok(tzinfo.DaylightDate.Day == 2, "tzinfo.DaylightDate.wDay expected '2', got '%d'.\n", tzinfo.DaylightDate.Day);
127     ok(tzinfo.DaylightDate.Weekday == 6, "tzinfo.DaylightDate.wDayOfWeek expected '6', got '%d'.\n", tzinfo.DaylightDate.Weekday);
128     ok(tzinfo.DaylightDate.Year == 0, "tzinfo.DaylightDate.wYear expected '0', got '%d'.\n", tzinfo.DaylightDate.Year);
129 
130     /* Check for the Standard Data Info */
131     ok(tzinfo.StandardDate.Month == 11, "tzinfo.StandardDate.wMonth expected '11', got '%d'.\n", tzinfo.StandardDate.Month);
132     ok(tzinfo.StandardDate.Day == 3, "tzinfo.StandardDate.wDay expected '3', got '%d'.\n", tzinfo.StandardDate.Day);
133     ok(tzinfo.StandardDate.Weekday == 5, "tzinfo.StandardDate.wDayOfWeek expected '5', got '%d'.\n", tzinfo.StandardDate.Weekday);
134     ok(tzinfo.StandardDate.Year == 0, "tzinfo.StandardDate.wYear expected '0', got '%d'.\n", tzinfo.StandardDate.Year);
135 
136     /* Check for the Bias Info */
137     ok(tzinfo.Bias == 360, "tzinfo.Bias expected '360', got '%ld'.\n", tzinfo.Bias);
138     ok(tzinfo.DaylightBias == -60, "tzinfo.DaylightBias expected '-60', got '%ld'.\n", tzinfo.DaylightBias);
139     ok(tzinfo.StandardBias == 120, "tzinfo.StandardBias expected '120', got '%ld'.\n", tzinfo.StandardBias);
140 
141     // Restore the original time zone information and put things back like we found them originally
142     ok(SetTimeZoneInformation(&tziOld),
143         "Set Time Zone Information failed with error = %ld.\n", GetLastError());
144 
145 }
146 
147 
148 START_TEST(RtlQueryTimeZoneInformation)
149 {
150     /* Test modeled after reactos\modules\rostests\winetests\ntdll\time.c for Vista+ */
151     HMODULE mod = GetModuleHandleA("ntdll.dll");
152     pRtlQueryTimeZoneInformation = (void *)GetProcAddress(mod, "RtlQueryTimeZoneInformation");
153 
154     test_RtlQueryTimeZoneInformation();
155 }