diff --git a/modules/rostests/apitests/ntdll/CMakeLists.txt b/modules/rostests/apitests/ntdll/CMakeLists.txt index 3e9756c7f3..5e9b237f18 100644 --- a/modules/rostests/apitests/ntdll/CMakeLists.txt +++ b/modules/rostests/apitests/ntdll/CMakeLists.txt @@ -49,6 +49,7 @@ list(APPEND SOURCE RtlMemoryStream.c RtlNtPathNameToDosPathName.c RtlpEnsureBufferSize.c + rtlquerytimezoneinfo.c RtlReAllocateHeap.c RtlUnicodeStringToAnsiString.c RtlUpcaseUnicodeStringToCountedOemString.c diff --git a/modules/rostests/apitests/ntdll/rtlquerytimezoneinfo.c b/modules/rostests/apitests/ntdll/rtlquerytimezoneinfo.c new file mode 100644 index 0000000000..2151bbbdf9 --- /dev/null +++ b/modules/rostests/apitests/ntdll/rtlquerytimezoneinfo.c @@ -0,0 +1,152 @@ +/* + * PROJECT: ntdll_apitest + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) + * PURPOSE: Tests for RtlQueryTimeZoneInformation + * COPYRIGHT: Copyright 2018 Doug Lyons + */ + +/* + * RTL_SYSTEM_TIME is almost the same as the SYSTEMTIME structure defined + * in winbase.h, however we need to define it differently here. + * This is used by RtlQueryTimeZoneInformation and RtlSetTimeZoneInformation. + * See: https://social.msdn.microsoft.com/Forums/en-US/home?forum=en-US and + * Search: Reading TimeZone binary data from registry by Patrick + * and then look at the last post showing typedef struct SYSTEMTIME_TZI. + */ +typedef struct _RTL_SYSTEM_TIME { + WORD wYear; + WORD wMonth; + WORD wDay; /* wDayOfWeek was here normally */ + WORD wHour; + WORD wMinute; + WORD wSecond; + WORD wMilliseconds; + WORD wDayOfWeek; /* wDayOfWeek relocated to here */ +} RTL_SYSTEM_TIME; + +/* + * RTL_TIME_ZONE_INFORMATION is the same as the TIME_ZONE_INFORMATION structure + * defined in winbase.h, however we need to define RTL_TIME_ZONE_INFORMATION + * seperately here so we don't depend on winbase.h. + * This is used by RtlQueryTimeZoneInformation and RtlSetTimeZoneInformation. + */ +typedef struct _RTL_TIME_ZONE_INFORMATION { + LONG Bias; + WCHAR StandardName[32]; + RTL_SYSTEM_TIME StandardDate; + LONG StandardBias; + WCHAR DaylightName[32]; + RTL_SYSTEM_TIME DaylightDate; + LONG DaylightBias; +} RTL_TIME_ZONE_INFORMATION; + +static NTSTATUS (WINAPI *pRtlQueryTimeZoneInformation)( RTL_TIME_ZONE_INFORMATION *); + +static void test_RtlQueryTimeZoneInformation(void) +{ + RTL_TIME_ZONE_INFORMATION tzinfo; + NTSTATUS status; + TIME_ZONE_INFORMATION tziOld, tziNew, tziTest; + DWORD dwRet; + + // Retrieve the current time zone information + + dwRet = GetTimeZoneInformation(&tziOld); + + ok(dwRet == TIME_ZONE_ID_STANDARD || dwRet == TIME_ZONE_ID_UNKNOWN || dwRet == TIME_ZONE_ID_DAYLIGHT, + "Get Time Zone Name failed with error = %ld.\n", GetLastError()); + + // Adjust the time zone information + + ZeroMemory(&tziNew, sizeof(tziNew)); + tziNew.Bias = 360; + wcscpy(tziNew.StandardName, L"Test Standard Zone"); + tziNew.StandardDate.wMonth = 11; + tziNew.StandardDate.wDayOfWeek = 5; + tziNew.StandardDate.wDay = 3; + tziNew.StandardDate.wHour = 2; + tziNew.StandardBias = 120; + + wcscpy(tziNew.DaylightName, L"Test Daylight Zone"); + tziNew.DaylightDate.wMonth = 4; + tziNew.DaylightDate.wDayOfWeek = 6; + tziNew.DaylightDate.wDay = 2; + tziNew.DaylightDate.wHour = 2; + tziNew.DaylightBias = -60; + + // Set up SetLastError with known value for later testing + + SetLastError(0xDEADBEEF); + + ok(SetTimeZoneInformation(&tziNew) , + "Set Time Zone Information failed with error = %ld.\n", GetLastError()); + + // if we got an error the function failed, so there is not much else we can do + + if(GetLastError() != 0xDEADBEEF) + { + win_skip("SetTimeZoneInformation() is not available, so tests cannot be run.\n"); + return; + } + + // Retrieve and display the newly set time zone information + + dwRet = GetTimeZoneInformation(&tziTest); + + ok(dwRet == TIME_ZONE_ID_STANDARD || dwRet == TIME_ZONE_ID_UNKNOWN || dwRet == TIME_ZONE_ID_DAYLIGHT, + "Get Time Zone Information Returned failed with error = %ld.\n", GetLastError()); + + ok(!wcscmp(tziTest.StandardName, tziNew.StandardName), + "Standard Time Zone Name = %ls, expected %ls.\n", tziTest.StandardName, tziNew.StandardName); + + ok(!wcscmp(tziTest.DaylightName, tziNew.DaylightName), + "Standard Time Zone Name = %ls, expected %ls.\n", tziTest.DaylightName, tziNew.DaylightName); + + /* test RtlQueryTimeZoneInformation returns a TIME_ZONE_INFORMATION structure */ + + if (!pRtlQueryTimeZoneInformation) + { + win_skip("pRtlQueryTimeZoneInformation() fails, so tests cannot be run.\n"); + return; + } + + /* Clear Time Zone Info field */ + memset(&tzinfo, 0, sizeof(tzinfo)); + + /* Read Time Zone Info */ + status = pRtlQueryTimeZoneInformation(&tzinfo); + ok(status == STATUS_SUCCESS, "pRtlQueryTimeZoneInformation failed, got %08x\n", (UINT) status); + + /* Check for the Daylight Date Info */ + ok(tzinfo.DaylightDate.wMonth == 4, "tzinfo.DaylightDate.wMonth expected '4', got '%d'.\n", tzinfo.DaylightDate.wMonth); + ok(tzinfo.DaylightDate.wDay == 2, "tzinfo.DaylightDate.wDay expected '2', got '%d'.\n", tzinfo.DaylightDate.wDay); + ok(tzinfo.DaylightDate.wDayOfWeek == 6, "tzinfo.DaylightDate.wDayOfWeek expected '6', got '%d'.\n", tzinfo.DaylightDate.wDayOfWeek); + ok(tzinfo.DaylightDate.wYear == 0, "tzinfo.DaylightDate.wYear expected '0', got '%d'.\n", tzinfo.DaylightDate.wYear); + + /* Check for the Standard Data Info */ + ok(tzinfo.StandardDate.wMonth == 11, "tzinfo.StandardDate.wMonth expected '11', got '%d'.\n", tzinfo.StandardDate.wMonth); + ok(tzinfo.StandardDate.wDay == 3, "tzinfo.StandardDate.wDay expected '3', got '%d'.\n", tzinfo.StandardDate.wDay); + ok(tzinfo.StandardDate.wDayOfWeek == 5, "tzinfo.StandardDate.wDayOfWeek expected '5', got '%d'.\n", tzinfo.StandardDate.wDayOfWeek); + ok(tzinfo.StandardDate.wYear == 0, "tzinfo.StandardDate.wYear expected '0', got '%d'.\n", tzinfo.StandardDate.wYear); + + /* Check for the Bias Info */ + ok(tzinfo.Bias == 360, "tzinfo.Bias expected '360', got '%ld'.\n", tzinfo.Bias); + ok(tzinfo.DaylightBias == -60, "tzinfo.DaylightBias expected '-60', got '%ld'.\n", tzinfo.DaylightBias); + ok(tzinfo.StandardBias == 120, "tzinfo.StandardBias expected '120', got '%ld'.\n", tzinfo.StandardBias); + + // Restore the original time zone information and put things back like we found them originally + + ok(SetTimeZoneInformation(&tziOld) , + "Set Time Zone Information failed with error = %ld.\n", GetLastError()); + +} + + +START_TEST(RtlQueryTimeZoneInformation) +{ +/* Test modeled after reactos\modules\rostests\winetests\ntdll\time.c for Vista+ */ + HMODULE mod = GetModuleHandleA("ntdll.dll"); + pRtlQueryTimeZoneInformation = (void *)GetProcAddress(mod, "RtlQueryTimeZoneInformation"); + + test_RtlQueryTimeZoneInformation(); +} diff --git a/modules/rostests/apitests/ntdll/testlist.c b/modules/rostests/apitests/ntdll/testlist.c index f17f87267c..c6afd1d342 100644 --- a/modules/rostests/apitests/ntdll/testlist.c +++ b/modules/rostests/apitests/ntdll/testlist.c @@ -53,6 +53,7 @@ extern void func_RtlIsNameLegalDOS8Dot3(void); extern void func_RtlMemoryStream(void); extern void func_RtlNtPathNameToDosPathName(void); extern void func_RtlpEnsureBufferSize(void); +extern void func_RtlQueryTimeZoneInformation(void); extern void func_RtlReAllocateHeap(void); extern void func_RtlUnicodeStringToAnsiString(void); extern void func_RtlUpcaseUnicodeStringToCountedOemString(void); @@ -111,6 +112,7 @@ const struct test winetest_testlist[] = { "RtlMemoryStream", func_RtlMemoryStream }, { "RtlNtPathNameToDosPathName", func_RtlNtPathNameToDosPathName }, { "RtlpEnsureBufferSize", func_RtlpEnsureBufferSize }, + { "RtlQueryTimeZoneInformation", func_RtlQueryTimeZoneInformation }, { "RtlReAllocateHeap", func_RtlReAllocateHeap }, { "RtlUnicodeStringToAnsiString", func_RtlUnicodeStringToAnsiString }, { "RtlUpcaseUnicodeStringToCountedOemString", func_RtlUpcaseUnicodeStringToCountedOemString },