// test_tz.cpp : Defines the entry point for the console application.
//
//
// Original Author: Jonathan M. Gilligan
//
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your
// option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// Modification History:
// 18 May 2001, JMG -- First version.
#include "stdafx.h"
#include "JmgStat.h"
namespace jmg = Jonathan_M_Gilligan_95724E90_4A88_11d5_80F3_006008C7B14D;
static const SYSTEMTIME newtime = {
1999, // wYear
11, // wMonth
2, // wDayOfWeek
30, // wDay
20, // wHour
45, // wMinute
49, // wSecond
0 // wMilliseconds
};
// print a report on file modification times computed using
// stat and GetMTime functions.
void Report(LPCTSTR name)
{
struct _stat s1;
time_t tm_jmg;
_tstat(name, &s1);
jmg::GetUTCFileModTime(name, & tm_jmg);
struct tm t1, t2, tl1, tl2;
t1 = * gmtime(&s1.st_mtime);
t2 = * gmtime(&tm_jmg);
tl1 = * localtime(&s1.st_mtime);
tl2 = * localtime(&tm_jmg);
char tbuf1[256], tbuf2[256],
tlbuf1[256], tlbuf2[256];
strcpy(tbuf1, asctime(&t1));
strcpy(tbuf2, asctime(&t2));
strcpy(tlbuf1, asctime(&tl1));
strcpy(tlbuf2, asctime(&tl2));
_tprintf(_T("File mod times (UTC):\n stat->\t%s jmg->\t\t%s.\n"),
tbuf1, tbuf2);
_tprintf(_T("File mod times (local):\n stat->\t%s jmg->\t\t%s.\n"),
tlbuf1, tlbuf2);
}
// Run "dir" to get the system's idea of the local file modification time...
void RunSystemDirCommand(LPCTSTR fname)
{
FILE * dirpipe = NULL;
_TCHAR dirbuf[128];
_TCHAR pszCommand[1024];
_sntprintf(pszCommand, sizeof(pszCommand), _T("dir \"%s\""), fname);
dirpipe = _tpopen(pszCommand, _T("rt"));
if (dirpipe) {
while (!feof(dirpipe)) {
if (_fgetts(dirbuf, sizeof(dirbuf), dirpipe)) {
_tprintf(dirbuf);
}
}
_pclose(dirpipe);
}
}
// get string representation of the local and utc times.
void MakeTimes(LPTSTR local, LPTSTR utc, LPTSTR daylight)
{
TIME_ZONE_INFORMATION zone;
DWORD dwZoneStatus;
_TCHAR * ptr;
time_t systemTime;
time(&systemTime);
_tcscpy(local, _tasctime(localtime(&systemTime)));
_tcscpy(utc, _tasctime(gmtime(&systemTime)));
ptr = _tcschr(local,_T('\n'));
if (ptr)
*ptr = _T('\0');
ptr = _tcschr(utc,_T('\n'));
if (ptr)
*ptr = _T('\0');
dwZoneStatus = GetTimeZoneInformation(&zone);
switch (dwZoneStatus) {
case TIME_ZONE_ID_STANDARD:
_tcscpy(daylight, _T("Standard"));
break;
case TIME_ZONE_ID_DAYLIGHT:
_tcscpy(daylight, _T("Daylight"));
break;
case TIME_ZONE_ID_UNKNOWN:
default:
_tcscpy(daylight, _T("Unknown"));
break;
}
}
// Create scratch files which we will use to test file modification times.
void CreateScratch(LPCTSTR fname)
{
FILE *scratch = _tfopen(fname, _T("wt"));
if (scratch) {
_ftprintf(scratch, _T("this is a test\n"));
fclose(scratch);
}
}
// Set the system Time Zone Information to Pacific time.
void SetPacificTime()
{
LONG result(0);
HKEY hTheKey(0);
TIME_ZONE_INFORMATION zone;
DWORD type(REG_BINARY);
struct TZI {
LONG Bias;
LONG StandardBias;
LONG DaylightBias;
SYSTEMTIME StandardDate;
SYSTEMTIME DaylightDate;
} tzi;
DWORD buflen(sizeof(tzi));
#if !defined(_UNICODE)
char buf[32];
DWORD xlen(0);
#endif
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
_T("Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\Pacific Standard Time"),
0, KEY_READ, &hTheKey);
if (result == ERROR_SUCCESS) {
result = RegQueryValueEx(hTheKey, _T("TZI"), NULL, &type,
reinterpret_cast<LPBYTE>(&tzi), &buflen );
if (result == ERROR_SUCCESS) {
zone.Bias = tzi.Bias;
zone.DaylightBias = tzi.DaylightBias;
zone.StandardBias = tzi.StandardBias;
zone.DaylightDate = tzi.DaylightDate;
zone.StandardDate = tzi.StandardDate;
type = REG_SZ;
#if defined(_UNICODE)
buflen = sizeof(zone.DaylightName);
result = RegQueryValueEx(hTheKey, _T("Dlt"), NULL, &type,
reinterpret_cast<LPBYTE>(& zone.DaylightName), &buflen);
#else
buflen = sizeof(buf);
result = RegQueryValueEx(hTheKey, _T("Dlt"), NULL, &type,
reinterpret_cast<LPBYTE>(buf), &buflen);
if (result == ERROR_SUCCESS) {
xlen = MultiByteToWideChar(CP_ACP, 0, buf, -1, zone.DaylightName, 32);
result = buflen != xlen ;
}
#endif
if (result != ERROR_SUCCESS) {
wcscpy(zone.DaylightName, L"xxx");
}
#if defined(_UNICODE)
buflen = sizeof(zone.StandardName);
result = RegQueryValueEx(hTheKey, _T("Std"), NULL, &type,
reinterpret_cast<LPBYTE>(zone.StandardName), &buflen);
#else
buflen = sizeof(buf);
result = RegQueryValueEx(hTheKey, _T("Std"), NULL, &type,
reinterpret_cast<LPBYTE>(buf), &buflen);
if (result == ERROR_SUCCESS) {
xlen = MultiByteToWideChar(CP_ACP, 0, buf, -1, zone.StandardName, 32);
result = buflen != xlen;
}
#endif
if (result != ERROR_SUCCESS) {
wcscpy(zone.DaylightName, L"yyy");
}
result = SetTimeZoneInformation(&zone);
}
}
_tzset();
}
// Run file modification time tests on the four files referred to by fnames.
void RunTests(LPCTSTR * fnames)
{
_TCHAR strLocal[256], strUTC[256], strDaylight[256];
SYSTEMTIME oldtime;
TIME_ZONE_INFORMATION zone;
DWORD dwDaylightStatus;
MakeTimes(strLocal, strUTC, strDaylight);
dwDaylightStatus = GetTimeZoneInformation(&zone);
_tprintf(_T("\n======================================================================")
_T("\nCurrent time:\n\t%s local (%s), %s UTC\n"),
strLocal, strDaylight, strUTC);
for (int i = 0; i < 4; ++i) {
RunSystemDirCommand(fnames[i]);
Report(fnames[i]);
}
GetSystemTime(&oldtime);
SetSystemTime(&newtime);
MakeTimes(strLocal, strUTC, strDaylight);
_tprintf(_T("\n======================================================================")
_T("\nCurrent time:\n\t%s local (%s), %s UTC\n"),
strLocal, strDaylight, strUTC);
for (i = 0; i < 4; ++i) {
RunSystemDirCommand(fnames[i]);
Report(fnames[i]);
}
SetSystemTime(&oldtime);
}
// Create scratch files used for modification time testing.
void CreateFiles(LPCTSTR fname_ntfs_dst, LPCTSTR fname_fat_dst,
LPCTSTR fname_ntfs_nodst, LPCTSTR fname_fat_nodst)
{
SYSTEMTIME oldtime;
CreateScratch(fname_ntfs_dst);
CreateScratch(fname_fat_dst);
GetSystemTime(&oldtime);
SetSystemTime(&newtime);
CreateScratch(fname_ntfs_nodst);
CreateScratch(fname_fat_nodst);
SetSystemTime(&oldtime);
}
// delete scratch files whose names are in fnames[0]..fnames[3]
void DeleteFiles(LPCTSTR *fnames)
{
for (int i = 0; i < 4; ++i) {
_tunlink(fnames[i]);
}
}
// Test file modification times for the four files.
void Test(LPCTSTR *fnames)
{
_tprintf(_T("\n**********************************************************************\n")
_T("Local timezone information:\n\t%ld, %ld, %d, %s, %s\n"),
_timezone, _dstbias, _daylight,
_tzname[0], _tzname[1]);
RunTests(fnames);
}
void usage(void)
{
_tprintf(_T("test_tz [-c[+|-]] [-d[+|-}] [-p[+|-]]\n")
_T(" -c: create new test files on c:\\ and a:\\ to test NTFS and FAT systems.\n")
_T(" -d: delete the test files when we're done.\n")
_T(" -p: set system time zone to pacific time before doing the tests.\n")
_T(" -h: print this help information\n"));
}
int _tmain(int argc, _TCHAR* argv[])
{
// LPCTSTR fname = _T("C:/Program Files/Microsoft Visual Studio/vc98/crt/src/ctime.c");
LPCTSTR fname_ntfs_dst = _T("C:\\ntfs_test_dst.txt");
LPCTSTR fname_ntfs_nodst = _T("C:\\ntfs_test_no_dst.txt");
LPCTSTR fname_fat_dst = _T("A:\\fat_test_dst.txt");
LPCTSTR fname_fat_nodst = _T("A:\\fat_test_no_dst.txt");
LPCTSTR fnames[] = {
fname_ntfs_dst,
fname_ntfs_nodst,
fname_fat_dst,
fname_fat_nodst
};
bool bCreate(true), bUsePacific(false), bDelete(true);
int index = 0;
assert(newtime.wYear == 1999);
assert(newtime.wMonth == 11);
assert(newtime.wDayOfWeek == 2);
assert(newtime.wDay == 30);
assert(newtime.wHour == 20);
assert(newtime.wMinute == 45);
assert(newtime.wSecond == 49);
assert(newtime.wMilliseconds == 0);
while(++index < argc) {
LPCTSTR pArg = argv[index] + _tcsspn(argv[index], _T("-/"));
bool flag;
flag = true;
switch (pArg[1]) {
case '+':
flag = true;
break;
case '-':
flag = false;
break;
}
switch (*pArg) {
case _T('c'):
case _T('C'):
bCreate = flag;
break;
case _T('d'):
case _T('D'):
bDelete = flag;
break;
case _T('p'):
case _T('P'):
bUsePacific = flag;
break;
case _T('h'):
case _T('H'):
usage();
return 0;
default:
_tprintf(_T("Illegal command line option '%c'.\n\n"), *pArg);
usage();
return 1;
}
}
TIME_ZONE_INFORMATION zone;
DWORD dwDSTStatus;
dwDSTStatus = GetTimeZoneInformation(&zone);
if (bUsePacific) {
SetPacificTime();
}
_tzset();
if (bCreate) {
CreateFiles(fname_ntfs_dst, fname_fat_dst,
fname_ntfs_nodst, fname_fat_nodst);
}
Test(fnames);
if (bDelete) {
DeleteFiles(fnames);
}
if (bUsePacific) {
SetTimeZoneInformation(&zone);
}
return 0;
}