windows-nt/Source/XPSP1/NT/ds/security/services/w32time/w32tm/othercmds.cpp

1614 lines
56 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/--------------------------------------------------------------------
// OtherCmds-implementation
// Copyright (C) Microsoft Corporation, 1999
//
// Created by: Louis Thomas (louisth), 2-17-00
//
// Other useful w32tm commands
//
#include "pch.h" // precompiled headers
//--------------------------------------------------------------------
//####################################################################
//##
//## Copied from c run time and modified to be 64bit capable
//##
#include <crt\limits.h>
/* flag values */
#define FL_UNSIGNED 1 /* wcstoul called */
#define FL_NEG 2 /* negative sign found */
#define FL_OVERFLOW 4 /* overflow occured */
#define FL_READDIGIT 8 /* we've read at least one correct digit */
MODULEPRIVATE unsigned __int64 my_wcstoxl (const WCHAR * nptr, WCHAR ** endptr, int ibase, int flags) {
const WCHAR *p;
WCHAR c;
unsigned __int64 number;
unsigned __int64 digval;
unsigned __int64 maxval;
p=nptr; /* p is our scanning pointer */
number=0; /* start with zero */
c=*p++; /* read char */
while (iswspace(c))
c=*p++; /* skip whitespace */
if (c=='-') {
flags|=FL_NEG; /* remember minus sign */
c=*p++;
}
else if (c=='+')
c=*p++; /* skip sign */
if (ibase<0 || ibase==1 || ibase>36) {
/* bad base! */
if (endptr)
/* store beginning of string in endptr */
*endptr=(wchar_t *)nptr;
return 0L; /* return 0 */
}
else if (ibase==0) {
/* determine base free-lance, based on first two chars of
string */
if (c != L'0')
ibase=10;
else if (*p==L'x' || *p==L'X')
ibase=16;
else
ibase=8;
}
if (ibase==16) {
/* we might have 0x in front of number; remove if there */
if (c==L'0' && (*p==L'x' || *p==L'X')) {
++p;
c=*p++; /* advance past prefix */
}
}
/* if our number exceeds this, we will overflow on multiply */
maxval=_UI64_MAX / ibase;
for (;;) { /* exit in middle of loop */
/* convert c to value */
if (iswdigit(c))
digval=c-L'0';
else if (iswalpha(c))
digval=(TCHAR)CharUpper((LPTSTR)c)-L'A'+10;
else
break;
if (digval>=(unsigned)ibase)
break; /* exit loop if bad digit found */
/* record the fact we have read one digit */
flags|=FL_READDIGIT;
/* we now need to compute number=number*base+digval,
but we need to know if overflow occured. This requires
a tricky pre-check. */
if (number<maxval || (number==maxval &&
(unsigned __int64)digval<=_UI64_MAX%ibase)) {
/* we won't overflow, go ahead and multiply */
number=number*ibase+digval;
}
else {
/* we would have overflowed -- set the overflow flag */
flags|=FL_OVERFLOW;
}
c=*p++; /* read next digit */
}
--p; /* point to place that stopped scan */
if (!(flags&FL_READDIGIT)) {
/* no number there; return 0 and point to beginning of
string */
if (endptr)
/* store beginning of string in endptr later on */
p=nptr;
number=0L; /* return 0 */
}
else if ((flags&FL_OVERFLOW) ||
(!(flags&FL_UNSIGNED) &&
(((flags&FL_NEG) && (number>-_I64_MIN)) ||
(!(flags&FL_NEG) && (number>_I64_MAX)))))
{
/* overflow or signed overflow occurred */
//errno=ERANGE;
if ( flags&FL_UNSIGNED )
number=_UI64_MAX;
else if ( flags&FL_NEG )
number=(unsigned __int64)(-_I64_MIN);
else
number=_I64_MAX;
}
if (endptr != NULL)
/* store pointer to char that stopped the scan */
*endptr=(wchar_t *)p;
if (flags&FL_NEG)
/* negate result if there was a neg sign */
number=(unsigned __int64)(-(__int64)number);
return number; /* done. */
}
MODULEPRIVATE unsigned __int64 wcstouI64(const WCHAR *nptr, WCHAR ** endptr, int ibase) {
return my_wcstoxl(nptr, endptr, ibase, FL_UNSIGNED);
}
//####################################################################
//--------------------------------------------------------------------
HRESULT myHExceptionCode(EXCEPTION_POINTERS * pep) {
HRESULT hr=pep->ExceptionRecord->ExceptionCode;
if (!FAILED(hr)) {
hr=HRESULT_FROM_WIN32(hr);
}
return hr;
}
//--------------------------------------------------------------------
// NOTE: this function is accessed through a hidden option, and does not need to be localized.
void PrintNtpPeerInfo(W32TIME_NTP_PEER_INFO *pnpInfo) {
LPWSTR pwszNULL = L"(null)";
wprintf(L"PEER: %s\n", pnpInfo->wszUniqueName ? pnpInfo->wszUniqueName : pwszNULL);
wprintf(L"ulSize: %d\n", pnpInfo->ulSize);
wprintf(L"ulResolveAttempts: %d\n", pnpInfo->ulResolveAttempts);
wprintf(L"u64TimeRemaining: %I64u\n", pnpInfo->u64TimeRemaining);
wprintf(L"u64LastSuccessfulSync: %I64u\n", pnpInfo->u64LastSuccessfulSync);
wprintf(L"ulLastSyncError: 0x%08X\n", pnpInfo->ulLastSyncError);
wprintf(L"ulLastSyncErrorMsgId: 0x%08X\n", pnpInfo->ulLastSyncErrorMsgId);
wprintf(L"ulValidDataCounter: %d\n", pnpInfo->ulValidDataCounter);
wprintf(L"ulAuthTypeMsgId: 0x%08X\n", pnpInfo->ulAuthTypeMsgId);
wprintf(L"ulMode: %d\n", pnpInfo->ulMode);
wprintf(L"ulStratum: %d\n", pnpInfo->ulStratum);
wprintf(L"ulReachability: %d\n", pnpInfo->ulReachability);
wprintf(L"ulPeerPollInterval: %d\n", pnpInfo->ulPeerPollInterval);
wprintf(L"ulHostPollInterval: %d\n", pnpInfo->ulHostPollInterval);
}
//--------------------------------------------------------------------
// NOTE: this function is accessed through a hidden option, and does not need to be localized.
void PrintNtpProviderData(W32TIME_NTP_PROVIDER_DATA *pNtpProviderData) {
wprintf(L"ulSize: %d, ulError: 0x%08X, ulErrorMsgId: 0x%08X, cPeerInfo: %d\n",
pNtpProviderData->ulSize,
pNtpProviderData->ulError,
pNtpProviderData->ulErrorMsgId,
pNtpProviderData->cPeerInfo
);
for (DWORD dwIndex = 0; dwIndex < pNtpProviderData->cPeerInfo; dwIndex++) {
wprintf(L"\n");
PrintNtpPeerInfo(&(pNtpProviderData->pPeerInfo[dwIndex]));
}
}
//--------------------------------------------------------------------
HRESULT PrintStr(HANDLE hOut, WCHAR * wszBuf)
{
return MyWriteConsole(hOut, wszBuf, wcslen(wszBuf));
}
//--------------------------------------------------------------------
HRESULT Print(HANDLE hOut, WCHAR * wszFormat, ...) {
WCHAR wszBuf[1024];
int nWritten;
va_list vlArgs;
va_start(vlArgs, wszFormat);
nWritten=_vsnwprintf(wszBuf, ARRAYSIZE(wszBuf)-1, wszFormat, vlArgs);
va_end(vlArgs);
wszBuf[ARRAYSIZE(wszBuf)-1]=L'\0';
return PrintStr(hOut, wszBuf);
}
//--------------------------------------------------------------------
MODULEPRIVATE HRESULT PrintNtTimeAsLocalTime(HANDLE hOut, unsigned __int64 qwTime) {
HRESULT hr;
FILETIME ftLocal;
SYSTEMTIME stLocal;
unsigned int nChars;
// must be cleaned up
WCHAR * wszDate=NULL;
WCHAR * wszTime=NULL;
if (!FileTimeToLocalFileTime((FILETIME *)(&qwTime), &ftLocal)) {
_JumpLastError(hr, error, "FileTimeToLocalFileTime");
}
if (!FileTimeToSystemTime(&ftLocal, &stLocal)) {
_JumpLastError(hr, error, "FileTimeToSystemTime");
}
nChars=GetDateFormat(NULL, 0, &stLocal, NULL, NULL, 0);
if (0==nChars) {
_JumpLastError(hr, error, "GetDateFormat");
}
wszDate=(WCHAR *)LocalAlloc(LPTR, nChars*sizeof(WCHAR));
_JumpIfOutOfMemory(hr, error, wszDate);
nChars=GetDateFormat(NULL, 0, &stLocal, NULL, wszDate, nChars);
if (0==nChars) {
_JumpLastError(hr, error, "GetDateFormat");
}
nChars=GetTimeFormat(NULL, 0, &stLocal, NULL, NULL, 0);
if (0==nChars) {
_JumpLastError(hr, error, "GetTimeFormat");
}
wszTime=(WCHAR *)LocalAlloc(LPTR, nChars*sizeof(WCHAR));
_JumpIfOutOfMemory(hr, error, wszTime);
nChars=GetTimeFormat(NULL, 0, &stLocal, NULL, wszTime, nChars);
if (0==nChars) {
_JumpLastError(hr, error, "GetTimeFormat");
}
Print(hOut, L"%s %s (local time)", wszDate, wszTime);
hr=S_OK;
error:
if (NULL!=wszDate) {
LocalFree(wszDate);
}
if (NULL!=wszTime) {
LocalFree(wszTime);
}
return hr;
}
//--------------------------------------------------------------------
void PrintNtTimePeriod(HANDLE hOut, NtTimePeriod tp) {
Print(hOut, L"%02I64u.%07I64us", tp.qw/10000000,tp.qw%10000000);
}
//--------------------------------------------------------------------
void PrintNtTimeOffset(HANDLE hOut, NtTimeOffset to) {
NtTimePeriod tp;
if (to.qw<0) {
PrintStr(hOut, L"-");
tp.qw=(unsigned __int64)-to.qw;
} else {
PrintStr(hOut, L"+");
tp.qw=(unsigned __int64)to.qw;
}
PrintNtTimePeriod(hOut, tp);
}
//####################################################################
//--------------------------------------------------------------------
void PrintHelpOtherCmds(void) {
UINT idsText[] = {
IDS_W32TM_OTHERCMDHELP_LINE1, IDS_W32TM_OTHERCMDHELP_LINE2,
IDS_W32TM_OTHERCMDHELP_LINE3, IDS_W32TM_OTHERCMDHELP_LINE4,
IDS_W32TM_OTHERCMDHELP_LINE5, IDS_W32TM_OTHERCMDHELP_LINE6,
IDS_W32TM_OTHERCMDHELP_LINE7, IDS_W32TM_OTHERCMDHELP_LINE8,
IDS_W32TM_OTHERCMDHELP_LINE9, IDS_W32TM_OTHERCMDHELP_LINE10,
IDS_W32TM_OTHERCMDHELP_LINE11, IDS_W32TM_OTHERCMDHELP_LINE12,
IDS_W32TM_OTHERCMDHELP_LINE13, IDS_W32TM_OTHERCMDHELP_LINE14,
IDS_W32TM_OTHERCMDHELP_LINE15, IDS_W32TM_OTHERCMDHELP_LINE16,
IDS_W32TM_OTHERCMDHELP_LINE17, IDS_W32TM_OTHERCMDHELP_LINE18,
IDS_W32TM_OTHERCMDHELP_LINE19, IDS_W32TM_OTHERCMDHELP_LINE20,
IDS_W32TM_OTHERCMDHELP_LINE21, IDS_W32TM_OTHERCMDHELP_LINE22,
IDS_W32TM_OTHERCMDHELP_LINE23, IDS_W32TM_OTHERCMDHELP_LINE24,
IDS_W32TM_OTHERCMDHELP_LINE25, IDS_W32TM_OTHERCMDHELP_LINE26,
IDS_W32TM_OTHERCMDHELP_LINE27, IDS_W32TM_OTHERCMDHELP_LINE28,
IDS_W32TM_OTHERCMDHELP_LINE29, IDS_W32TM_OTHERCMDHELP_LINE30,
IDS_W32TM_OTHERCMDHELP_LINE31, IDS_W32TM_OTHERCMDHELP_LINE32,
IDS_W32TM_OTHERCMDHELP_LINE33, IDS_W32TM_OTHERCMDHELP_LINE34,
IDS_W32TM_OTHERCMDHELP_LINE35, IDS_W32TM_OTHERCMDHELP_LINE36,
IDS_W32TM_OTHERCMDHELP_LINE37, IDS_W32TM_OTHERCMDHELP_LINE38,
IDS_W32TM_OTHERCMDHELP_LINE39, IDS_W32TM_OTHERCMDHELP_LINE40,
IDS_W32TM_OTHERCMDHELP_LINE41, IDS_W32TM_OTHERCMDHELP_LINE42,
IDS_W32TM_OTHERCMDHELP_LINE43, IDS_W32TM_OTHERCMDHELP_LINE44,
IDS_W32TM_OTHERCMDHELP_LINE45, IDS_W32TM_OTHERCMDHELP_LINE46,
IDS_W32TM_OTHERCMDHELP_LINE47, IDS_W32TM_OTHERCMDHELP_LINE48,
IDS_W32TM_OTHERCMDHELP_LINE49, IDS_W32TM_OTHERCMDHELP_LINE50,
IDS_W32TM_OTHERCMDHELP_LINE51, IDS_W32TM_OTHERCMDHELP_LINE52,
IDS_W32TM_OTHERCMDHELP_LINE53, IDS_W32TM_OTHERCMDHELP_LINE54,
IDS_W32TM_OTHERCMDHELP_LINE55, IDS_W32TM_OTHERCMDHELP_LINE56,
IDS_W32TM_OTHERCMDHELP_LINE57, IDS_W32TM_OTHERCMDHELP_LINE58,
IDS_W32TM_OTHERCMDHELP_LINE59, IDS_W32TM_OTHERCMDHELP_LINE60
};
for (int n=0; n<ARRAYSIZE(idsText); n++) {
LocalizedWPrintf(idsText[n]);
}
}
//--------------------------------------------------------------------
HRESULT PrintNtte(CmdArgs * pca) {
HRESULT hr;
unsigned __int64 qwTime;
HANDLE hOut;
// must be cleaned up
WCHAR * wszDate=NULL;
WCHAR * wszTime=NULL;
if (pca->nNextArg!=pca->nArgs-1) {
if (pca->nNextArg==pca->nArgs) {
LocalizedWPrintfCR(IDS_W32TM_ERRORGENERAL_MISSING_PARAM);
} else {
LocalizedWPrintfCR(IDS_W32TM_ERRORGENERAL_TOO_MANY_PARAMS);
}
hr=E_INVALIDARG;
_JumpError(hr, error, "(command line parsing)");
}
qwTime=wcstouI64(pca->rgwszArgs[pca->nNextArg], NULL, 0);
{
unsigned __int64 qwTemp=qwTime;
DWORD dwNanoSecs=(DWORD)(qwTemp%10000000);
qwTemp/=10000000;
DWORD dwSecs=(DWORD)(qwTemp%60);
qwTemp/=60;
DWORD dwMins=(DWORD)(qwTemp%60);
qwTemp/=60;
DWORD dwHours=(DWORD)(qwTemp%24);
DWORD dwDays=(DWORD)(qwTemp/24);
DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_W32TM_NTTE, dwDays, dwHours, dwMins, dwSecs, dwNanoSecs);
}
hOut=GetStdHandle(STD_OUTPUT_HANDLE);
if (INVALID_HANDLE_VALUE==hOut) {
_JumpLastError(hr, error, "GetStdHandle");
}
hr=PrintNtTimeAsLocalTime(hOut, qwTime);
if (FAILED(hr)) {
if (HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)==hr) {
LocalizedWPrintfCR(IDS_W32TM_ERRORGENERAL_INVALID_LOCALTIME);
} else {
_JumpError(hr, error, "PrintNtTimeAsLocalTime");
}
}
wprintf(L"\n");
hr=S_OK;
error:
if (NULL!=wszDate) {
LocalFree(wszDate);
}
if (NULL!=wszTime) {
LocalFree(wszTime);
}
return hr;
}
//--------------------------------------------------------------------
HRESULT PrintNtpte(CmdArgs * pca) {
HRESULT hr;
unsigned __int64 qwTime;
HANDLE hOut;
// must be cleaned up
WCHAR * wszDate=NULL;
WCHAR * wszTime=NULL;
if (pca->nNextArg!=pca->nArgs-1) {
if (pca->nNextArg==pca->nArgs) {
LocalizedWPrintfCR(IDS_W32TM_ERRORGENERAL_MISSING_PARAM);
} else {
LocalizedWPrintfCR(IDS_W32TM_ERRORGENERAL_TOO_MANY_PARAMS);
}
hr=E_INVALIDARG;
_JumpError(hr, error, "(command line parsing)");
}
qwTime=wcstouI64(pca->rgwszArgs[pca->nNextArg], NULL, 0);
{
NtpTimeEpoch teNtp={qwTime};
qwTime=NtTimeEpochFromNtpTimeEpoch(teNtp).qw;
unsigned __int64 qwTemp=qwTime;
DWORD dwNanoSecs=(DWORD)(qwTemp%10000000);
qwTemp/=10000000;
DWORD dwSecs=(DWORD)(qwTemp%60);
qwTemp/=60;
DWORD dwMins=(DWORD)(qwTemp%60);
qwTemp/=60;
DWORD dwHours=(DWORD)(qwTemp%24);
DWORD dwDays=(DWORD)(qwTemp/24);
DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_W32TM_NTPTE, qwTime, dwDays, dwHours, dwMins, dwSecs, dwNanoSecs);
}
hOut=GetStdHandle(STD_OUTPUT_HANDLE);
if (INVALID_HANDLE_VALUE==hOut) {
_JumpLastError(hr, error, "GetStdHandle")
}
hr=PrintNtTimeAsLocalTime(hOut, qwTime);
if (FAILED(hr)) {
if (HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)==hr) {
LocalizedWPrintf(IDS_W32TM_ERRORGENERAL_INVALID_LOCALTIME);
} else {
_JumpError(hr, error, "PrintNtTimeAsLocalTime");
}
}
wprintf(L"\n");
hr=S_OK;
error:
if (NULL!=wszDate) {
LocalFree(wszDate);
}
if (NULL!=wszTime) {
LocalFree(wszTime);
}
return hr;
}
//--------------------------------------------------------------------
// NOTE: this function is accessed through a hidden option, and does not need to be localized.
HRESULT SysExpr(CmdArgs * pca) {
HRESULT hr;
unsigned __int64 qwExprDate;
HANDLE hOut;
hr=VerifyAllArgsUsed(pca);
_JumpIfError(hr, error, "VerifyAllArgsUsed");
hOut=GetStdHandle(STD_OUTPUT_HANDLE);
if (INVALID_HANDLE_VALUE==hOut) {
_JumpLastError(hr, error, "GetStdHandle")
}
GetSysExpirationDate(&qwExprDate);
wprintf(L"0x%016I64X - ", qwExprDate);
if (0==qwExprDate) {
wprintf(L"no expiration date\n");
} else {
hr=PrintNtTimeAsLocalTime(hOut, qwExprDate);
_JumpIfError(hr, error, "PrintNtTimeAsLocalTime")
wprintf(L"\n");
}
hr=S_OK;
error:
return hr;
}
//--------------------------------------------------------------------
HRESULT ResyncCommand(CmdArgs * pca) {
HANDLE hTimeSlipEvent = NULL;
HRESULT hr;
WCHAR * wszComputer=NULL;
WCHAR * wszComputerDisplay;
bool bUseDefaultErrorPrinting = false;
bool bHard=true;
bool bNoWait=false;
bool bRediscover=false;
unsigned int nArgID;
DWORD dwResult;
DWORD dwSyncFlags=0;
// must be cleaned up
WCHAR * wszError=NULL;
// find out what computer to resync
if (FindArg(pca, L"computer", &wszComputer, &nArgID)) {
MarkArgUsed(pca, nArgID);
}
wszComputerDisplay=wszComputer;
if (NULL==wszComputerDisplay) {
wszComputerDisplay=L"local computer";
}
// find out if we need to use the w32tm named timeslip event to resync
if (FindArg(pca, L"event", NULL, &nArgID)) {
MarkArgUsed(pca, nArgID);
hr=VerifyAllArgsUsed(pca);
_JumpIfError(hr, error, "VerifyAllArgsUsed");
hTimeSlipEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, W32TIME_NAMED_EVENT_SYSTIME_NOT_CORRECT);
if (NULL == hTimeSlipEvent) {
bUseDefaultErrorPrinting = true;
_JumpLastError(hr, error, "OpenEvent");
}
if (!SetEvent(hTimeSlipEvent)) {
bUseDefaultErrorPrinting = true;
_JumpLastError(hr, error, "SetEvent");
}
} else {
// find out if we need to do a soft resync
if (FindArg(pca, L"soft", NULL, &nArgID)) {
MarkArgUsed(pca, nArgID);
dwSyncFlags = TimeSyncFlag_SoftResync;
} else if (FindArg(pca, L"update", NULL, &nArgID)) {
MarkArgUsed(pca, nArgID);
dwSyncFlags = TimeSyncFlag_UpdateAndResync;
} else if (FindArg(pca, L"rediscover", NULL, &nArgID)) {
// find out if we need to do a rediscover
MarkArgUsed(pca, nArgID);
dwSyncFlags = TimeSyncFlag_Rediscover;
} else {
dwSyncFlags = TimeSyncFlag_HardResync;
}
// find out if we don't want to wait
if (FindArg(pca, L"nowait", NULL, &nArgID)) {
MarkArgUsed(pca, nArgID);
bNoWait=true;
}
hr=VerifyAllArgsUsed(pca);
_JumpIfError(hr, error, "VerifyAllArgsUsed");
if (bRediscover && !bHard) {
LocalizedWPrintfCR(IDS_W32TM_WARN_IGNORE_SOFT);
}
LocalizedWPrintf2(IDS_W32TM_STATUS_SENDING_RESYNC_TO, L" %s...\n", wszComputerDisplay);
dwResult=W32TimeSyncNow(wszComputer, !bNoWait, TimeSyncFlag_ReturnResult | dwSyncFlags);
if (ResyncResult_Success==dwResult) {
LocalizedWPrintfCR(IDS_W32TM_ERRORGENERAL_COMMAND_SUCCESSFUL);
} else if (ResyncResult_NoData==dwResult) {
LocalizedWPrintfCR(IDS_W32TM_ERRORRESYNC_NO_TIME_DATA);
} else if (ResyncResult_StaleData==dwResult) {
LocalizedWPrintfCR(IDS_W32TM_ERRORRESYNC_STALE_DATA);
} else if (ResyncResult_Shutdown==dwResult) {
LocalizedWPrintfCR(IDS_W32TM_ERRORRESYNC_SHUTTING_DOWN);
} else if (ResyncResult_ChangeTooBig==dwResult) {
LocalizedWPrintfCR(IDS_W32TM_ERRORRESYNC_CHANGE_TOO_BIG);
} else {
bUseDefaultErrorPrinting = true;
hr = HRESULT_FROM_WIN32(dwResult);
_JumpError(hr, error, "W32TimeSyncNow");
}
}
hr=S_OK;
error:
if (FAILED(hr)) {
HRESULT hr2 = GetSystemErrorString(hr, &wszError);
_IgnoreIfError(hr2, "GetSystemErrorString");
if (SUCCEEDED(hr2)) {
LocalizedWPrintf2(IDS_W32TM_ERRORGENERAL_ERROR_OCCURED, L" %s\n", wszError);
}
}
if (NULL!=hTimeSlipEvent) {
CloseHandle(hTimeSlipEvent);
}
if (NULL!=wszError) {
LocalFree(wszError);
}
return hr;
}
//--------------------------------------------------------------------
HRESULT Stripchart(CmdArgs * pca) {
HRESULT hr;
WCHAR * wszParam;
WCHAR * wszComputer;
bool bDataOnly=false;
unsigned int nArgID;
unsigned int nIpAddrs;
TIME_ZONE_INFORMATION timezoneinfo;
signed __int64 nFullTzBias;
DWORD dwTimeZoneMode;
DWORD dwSleepSeconds;
HANDLE hOut;
bool bDontRunForever=false;
unsigned int nSamples;
NtTimeEpoch teNow;
// must be cleaned up
WCHAR * wszError=NULL;
bool bSocketLayerOpened=false;
in_addr * rgiaLocalIpAddrs=NULL;
in_addr * rgiaRemoteIpAddrs=NULL;
// find out what computer to watch
if (FindArg(pca, L"computer", &wszComputer, &nArgID)) {
MarkArgUsed(pca, nArgID);
} else {
LocalizedWPrintfCR(IDS_W32TM_ERRORPARAMETER_COMPUTER_MISSING);
hr=E_INVALIDARG;
_JumpError(hr, error, "command line parsing");
}
// find out how often to watch
if (FindArg(pca, L"period", &wszParam, &nArgID)) {
MarkArgUsed(pca, nArgID);
dwSleepSeconds=wcstoul(wszParam, NULL, 0);
if (dwSleepSeconds<1) {
dwSleepSeconds=1;
}
} else {
dwSleepSeconds=2;
}
// find out if we want a limited number of samples
if (FindArg(pca, L"samples", &wszParam, &nArgID)) {
MarkArgUsed(pca, nArgID);
bDontRunForever=true;
nSamples=wcstoul(wszParam, NULL, 0);
}
// find out if we only want to dump data
if (FindArg(pca, L"dataonly", NULL, &nArgID)) {
MarkArgUsed(pca, nArgID);
bDataOnly=true;
}
// redirect to file handled via stdout
hOut=GetStdHandle(STD_OUTPUT_HANDLE);
if (INVALID_HANDLE_VALUE==hOut) {
_JumpLastError(hr, error, "GetStdHandle")
}
hr=VerifyAllArgsUsed(pca);
_JumpIfError(hr, error, "VerifyAllArgsUsed");
dwTimeZoneMode=GetTimeZoneInformation(&timezoneinfo);
if (TIME_ZONE_ID_INVALID==dwTimeZoneMode) {
_JumpLastError(hr, error, "GetTimeZoneInformation");
} else if (TIME_ZONE_ID_DAYLIGHT==dwTimeZoneMode) {
nFullTzBias=(signed __int64)(timezoneinfo.Bias+timezoneinfo.DaylightBias);
} else {
nFullTzBias=(signed __int64)(timezoneinfo.Bias+timezoneinfo.StandardBias);
}
nFullTzBias*=600000000; // convert to from minutes to 10^-7s
hr=OpenSocketLayer();
_JumpIfError(hr, error, "OpenSocketLayer");
bSocketLayerOpened=true;
hr=MyGetIpAddrs(wszComputer, &rgiaLocalIpAddrs, &rgiaRemoteIpAddrs, &nIpAddrs, NULL);
_JumpIfError(hr, error, "MyGetIpAddrs");
// write out who we are tracking
Print(hOut, L"Tracking %s [%u.%u.%u.%u].\n",
wszComputer,
rgiaRemoteIpAddrs[0].S_un.S_un_b.s_b1, rgiaRemoteIpAddrs[0].S_un.S_un_b.s_b2,
rgiaRemoteIpAddrs[0].S_un.S_un_b.s_b3, rgiaRemoteIpAddrs[0].S_un.S_un_b.s_b4);
if (bDontRunForever) {
Print(hOut, L"Collecting %u samples.\n", nSamples);
}
// Write out the current time in full, since we will be using abbreviations later.
PrintStr(hOut, L"The current time is ");
AccurateGetSystemTime(&teNow.qw);
PrintNtTimeAsLocalTime(hOut, teNow.qw);
PrintStr(hOut, L".\n");
while (false==bDontRunForever || nSamples>0) {
const DWORD c_dwTimeout=1000;
NtpPacket npPacket;
NtTimeEpoch teDestinationTimestamp;
DWORD dwSecs;
DWORD dwMins;
DWORD dwHours;
signed int nMsMin=-10000;
signed int nMsMax=10000;
unsigned int nGraphWidth=55;
AccurateGetSystemTime(&teNow.qw);
teNow.qw-=nFullTzBias;
teNow.qw/=10000000;
dwSecs=(DWORD)(teNow.qw%60);
teNow.qw/=60;
dwMins=(DWORD)(teNow.qw%60);
teNow.qw/=60;
dwHours=(DWORD)(teNow.qw%24);
if (!bDataOnly) {
Print(hOut, L"%02u:%02u:%02u ", dwHours, dwMins, dwSecs);
} else {
Print(hOut, L"%02u:%02u:%02u, ", dwHours, dwMins, dwSecs);
}
hr=MyNtpPing(&(rgiaRemoteIpAddrs[0]), c_dwTimeout, &npPacket, &teDestinationTimestamp);
if (FAILED(hr)) {
Print(hOut, L"error: 0x%08X", hr);
} else {
// calculate the offset
NtTimeEpoch teOriginateTimestamp=NtTimeEpochFromNtpTimeEpoch(npPacket.teOriginateTimestamp);
NtTimeEpoch teReceiveTimestamp=NtTimeEpochFromNtpTimeEpoch(npPacket.teReceiveTimestamp);
NtTimeEpoch teTransmitTimestamp=NtTimeEpochFromNtpTimeEpoch(npPacket.teTransmitTimestamp);
NtTimeOffset toLocalClockOffset=
(teReceiveTimestamp-teOriginateTimestamp)
+ (teTransmitTimestamp-teDestinationTimestamp);
toLocalClockOffset/=2;
// calculate the delay
NtTimeOffset toRoundtripDelay=
(teDestinationTimestamp-teOriginateTimestamp)
- (teTransmitTimestamp-teReceiveTimestamp);
if (!bDataOnly) {
PrintStr(hOut, L"d:");
PrintNtTimeOffset(hOut, toRoundtripDelay);
PrintStr(hOut, L" o:");
PrintNtTimeOffset(hOut, toLocalClockOffset);
} else {
PrintNtTimeOffset(hOut, toLocalClockOffset);
}
// draw graph
if (!bDataOnly) {
unsigned int nSize=nMsMax-nMsMin+1;
double dRatio=((double)nGraphWidth)/nSize;
signed int nPoint=(signed int)(toLocalClockOffset.qw/10000);
bool bOutOfRange=false;
if (nPoint>nMsMax) {
nPoint=nMsMax;
bOutOfRange=true;
} else if (nPoint<nMsMin) {
nPoint=nMsMin;
bOutOfRange=true;
}
unsigned int nLeftOffset=(unsigned int)((nPoint-nMsMin)*dRatio);
unsigned int nZeroOffset=(unsigned int)((0-nMsMin)*dRatio);
PrintStr(hOut, L" [");
unsigned int nIndex;
for (nIndex=0; nIndex<nGraphWidth; nIndex++) {
if (nIndex==nLeftOffset) {
if (bOutOfRange) {
PrintStr(hOut, L"@");
} else {
PrintStr(hOut, L"*");
}
} else if (nIndex==nZeroOffset) {
PrintStr(hOut, L"|");
} else {
PrintStr(hOut, L" ");
}
}
PrintStr(hOut, L"]");
} // <- end drawing graph
} // <- end if sample received
PrintStr(hOut, L"\n");
nSamples--;
if (0!=nSamples) {
Sleep(dwSleepSeconds*1000);
}
} // <- end sample collection loop
hr=S_OK;
error:
if (NULL!=rgiaLocalIpAddrs) {
LocalFree(rgiaLocalIpAddrs);
}
if (NULL!=rgiaRemoteIpAddrs) {
LocalFree(rgiaRemoteIpAddrs);
}
if (bSocketLayerOpened) {
HRESULT hr2=CloseSocketLayer();
_TeardownError(hr, hr2, "CloseSocketLayer");
}
if (FAILED(hr)) {
WCHAR * wszError;
HRESULT hr2=GetSystemErrorString(hr, &wszError);
if (FAILED(hr2)) {
_IgnoreError(hr2, "GetSystemErrorString");
} else {
LocalizedWPrintf2(IDS_W32TM_ERRORGENERAL_ERROR_OCCURED, L" %s\n", wszError);
LocalFree(wszError);
}
}
return hr;
}
//--------------------------------------------------------------------
HRESULT Config(CmdArgs * pca) {
HRESULT hr;
DWORD dwRetval;
WCHAR * wszParam;
WCHAR * wszComputer;
unsigned int nArgID;
bool bManualPeerList=false;
bool bUpdate=false;
bool bSyncFromFlags=false;
bool bLocalClockDispersion=false;
unsigned int nManualPeerListLenBytes;
DWORD dwSyncFromFlags;
DWORD dwLocalClockDispersion;
// must be cleaned up
WCHAR * mwszManualPeerList=NULL;
HKEY hkLMRemote=NULL;
HKEY hkW32TimeConfig=NULL;
HKEY hkW32TimeParameters=NULL;
SC_HANDLE hSCM=NULL;
SC_HANDLE hTimeService=NULL;
// find out what computer to talk to
if (FindArg(pca, L"computer", &wszComputer, &nArgID)) {
MarkArgUsed(pca, nArgID);
} else {
// modifying local computer
wszComputer=NULL;
}
// find out if we want to notify the service
if (FindArg(pca, L"update", NULL, &nArgID)) {
MarkArgUsed(pca, nArgID);
bUpdate=true;
}
// see if they want to change the manual peer list
if (FindArg(pca, L"manualpeerlist", &wszParam, &nArgID)) {
MarkArgUsed(pca, nArgID);
nManualPeerListLenBytes=(wcslen(wszParam)+1)*sizeof(WCHAR);
mwszManualPeerList=(WCHAR *)LocalAlloc(LPTR, nManualPeerListLenBytes);
_JumpIfOutOfMemory(hr, error, mwszManualPeerList);
wcscpy(mwszManualPeerList, wszParam);
bManualPeerList=true;
}
// see if they want to change the syncfromflags
if (FindArg(pca, L"syncfromflags", &wszParam, &nArgID)) {
MarkArgUsed(pca, nArgID);
// find keywords in the string
dwSyncFromFlags=0;
WCHAR * wszKeyword=wszParam;
bool bLastKeyword=false;
while (false==bLastKeyword) {
WCHAR * wszNext=wcschr(wszKeyword, L',');
if (NULL==wszNext) {
bLastKeyword=true;
} else {
wszNext[0]=L'\0';
wszNext++;
}
if (L'\0'==wszKeyword[0]) {
// 'empty' keyword - no changes, but can be used to sync from nowhere.
} else if (0==_wcsicmp(L"manual", wszKeyword)) {
dwSyncFromFlags|=NCSF_ManualPeerList;
} else if (0==_wcsicmp(L"domhier", wszKeyword)) {
dwSyncFromFlags|=NCSF_DomainHierarchy;
} else {
LocalizedWPrintf2(IDS_W32TM_ERRORPARAMETER_UNKNOWN_PARAMETER_SYNCFROMFLAGS, L" '%s'.\n", wszKeyword);
hr=E_INVALIDARG;
_JumpError(hr, error, "command line parsing");
}
wszKeyword=wszNext;
}
bSyncFromFlags=true;
}
// see if they want to change the local clock dispersion
if (FindArg(pca, L"localclockdispersion", &wszParam, &nArgID)) {
MarkArgUsed(pca, nArgID);
dwLocalClockDispersion=wcstoul(wszParam, NULL, 0);
bLocalClockDispersion=true;
}
hr=VerifyAllArgsUsed(pca);
_JumpIfError(hr, error, "VerifyAllArgsUsed");
if (!bManualPeerList && !bSyncFromFlags && !bUpdate && !bLocalClockDispersion) {
LocalizedWPrintfCR(IDS_W32TM_ERRORCONFIG_NO_CHANGE_SPECIFIED);
hr=E_INVALIDARG;
_JumpError(hr, error, "command line parsing");
}
// make registry changes
if (bManualPeerList || bSyncFromFlags || bLocalClockDispersion) {
// open the key
dwRetval=RegConnectRegistry(wszComputer, HKEY_LOCAL_MACHINE, &hkLMRemote);
if (ERROR_SUCCESS!=dwRetval) {
hr=HRESULT_FROM_WIN32(dwRetval);
_JumpError(hr, error, "RegConnectRegistry");
}
// set "w32time\parameters" reg values
if (bManualPeerList || bSyncFromFlags) {
dwRetval=RegOpenKey(hkLMRemote, wszW32TimeRegKeyParameters, &hkW32TimeParameters);
if (ERROR_SUCCESS!=dwRetval) {
hr=HRESULT_FROM_WIN32(dwRetval);
_JumpError(hr, error, "RegOpenKey");
}
if (bManualPeerList) {
dwRetval=RegSetValueEx(hkW32TimeParameters, wszW32TimeRegValueNtpServer, 0, REG_SZ, (BYTE *)mwszManualPeerList, nManualPeerListLenBytes);
if (ERROR_SUCCESS!=dwRetval) {
hr=HRESULT_FROM_WIN32(dwRetval);
_JumpError(hr, error, "RegSetValueEx");
}
}
if (bSyncFromFlags) {
LPWSTR pwszType;
switch (dwSyncFromFlags) {
case NCSF_NoSync: pwszType = W32TM_Type_NoSync; break;
case NCSF_ManualPeerList: pwszType = W32TM_Type_NTP; break;
case NCSF_DomainHierarchy: pwszType = W32TM_Type_NT5DS; break;
case NCSF_ManualAndDomhier: pwszType = W32TM_Type_AllSync; break;
default:
hr = E_NOTIMPL;
_JumpError(hr, error, "SyncFromFlags not supported.");
}
dwRetval=RegSetValueEx(hkW32TimeParameters, wszW32TimeRegValueType, 0, REG_SZ, (BYTE *)pwszType, (wcslen(pwszType)+1) * sizeof(WCHAR));
if (ERROR_SUCCESS!=dwRetval) {
hr=HRESULT_FROM_WIN32(dwRetval);
_JumpError(hr, error, "RegSetValueEx");
}
}
}
if (bLocalClockDispersion) {
dwRetval=RegOpenKey(hkLMRemote, wszW32TimeRegKeyConfig, &hkW32TimeConfig);
if (ERROR_SUCCESS!=dwRetval) {
hr=HRESULT_FROM_WIN32(dwRetval);
_JumpError(hr, error, "RegOpenKey");
}
dwRetval=RegSetValueEx(hkW32TimeConfig, wszW32TimeRegValueLocalClockDispersion, 0, REG_DWORD, (BYTE *)&dwLocalClockDispersion, sizeof(dwLocalClockDispersion));
if (ERROR_SUCCESS!=dwRetval) {
hr=HRESULT_FROM_WIN32(dwRetval);
_JumpError(hr, error, "RegSetValueEx");
}
}
}
// send service message
if (bUpdate) {
SERVICE_STATUS servicestatus;
hSCM=OpenSCManager(wszComputer, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
if (NULL==hSCM) {
_JumpLastError(hr, error, "OpenSCManager");
}
hTimeService=OpenService(hSCM, L"w32time", SERVICE_PAUSE_CONTINUE);
if (NULL==hTimeService) {
_JumpLastError(hr, error, "OpenService");
}
if (!ControlService(hTimeService, SERVICE_CONTROL_PARAMCHANGE, &servicestatus)) {
_JumpLastError(hr, error, "ControlService");
}
}
hr=S_OK;
error:
if (NULL!=mwszManualPeerList) {
LocalFree(mwszManualPeerList);
}
if (NULL!=hkW32TimeConfig) {
RegCloseKey(hkW32TimeConfig);
}
if (NULL!=hkW32TimeParameters) {
RegCloseKey(hkW32TimeParameters);
}
if (NULL!=hkLMRemote) {
RegCloseKey(hkLMRemote);
}
if (NULL!=hTimeService) {
CloseServiceHandle(hTimeService);
}
if (NULL!=hSCM) {
CloseServiceHandle(hSCM);
}
if (FAILED(hr) && E_INVALIDARG!=hr) {
WCHAR * wszError;
HRESULT hr2=GetSystemErrorString(hr, &wszError);
if (FAILED(hr2)) {
_IgnoreError(hr2, "GetSystemErrorString");
} else {
LocalizedWPrintf2(IDS_W32TM_ERRORGENERAL_ERROR_OCCURED, L" %s\n", wszError);
LocalFree(wszError);
}
} else if (S_OK==hr) {
LocalizedWPrintfCR(IDS_W32TM_ERRORGENERAL_COMMAND_SUCCESSFUL);
}
return hr;
}
//--------------------------------------------------------------------
// NOTE: this function is accessed through a hidden option, and does not need to be localized.
HRESULT TestInterface(CmdArgs * pca) {
HRESULT hr;
WCHAR * wszComputer=NULL;
WCHAR * wszComputerDisplay;
unsigned int nArgID;
DWORD dwResult;
unsigned long ulBits;
void (* pfnW32TimeVerifyJoinConfig)(void);
void (* pfnW32TimeVerifyUnjoinConfig)(void);
// must be cleaned up
WCHAR * wszError=NULL;
HMODULE hmW32Time=NULL;
// check for gnsb (get netlogon service bits)
if (true==CheckNextArg(pca, L"gnsb", NULL)) {
// find out what computer to resync
if (FindArg(pca, L"computer", &wszComputer, &nArgID)) {
MarkArgUsed(pca, nArgID);
}
wszComputerDisplay=wszComputer;
if (NULL==wszComputerDisplay) {
wszComputerDisplay=L"local computer";
}
hr=VerifyAllArgsUsed(pca);
_JumpIfError(hr, error, "VerifyAllArgsUsed");
LocalizedWPrintf2(IDS_W32TM_STATUS_CALLING_GETNETLOGONBITS_ON, L" %s.\n", wszComputerDisplay);
dwResult=W32TimeGetNetlogonServiceBits(wszComputer, &ulBits);
if (S_OK==dwResult) {
wprintf(L"Bits: 0x%08X\n", ulBits);
} else {
hr=GetSystemErrorString(HRESULT_FROM_WIN32(dwResult), &wszError);
_JumpIfError(hr, error, "GetSystemErrorString");
LocalizedWPrintf2(IDS_W32TM_ERRORGENERAL_ERROR_OCCURED, L" %s\n", wszError);
}
// check for vjc (verify join config)
} else if (true==CheckNextArg(pca, L"vjc", NULL)) {
hr=VerifyAllArgsUsed(pca);
_JumpIfError(hr, error, "VerifyAllArgsUsed");
LocalizedWPrintfCR(IDS_W32TM_STATUS_CALLING_JOINCONFIG);
hmW32Time=LoadLibrary(wszDLLNAME);
if (NULL==hmW32Time) {
_JumpLastError(hr, vjcerror, "LoadLibrary");
}
pfnW32TimeVerifyJoinConfig=(void (*)(void))GetProcAddress(hmW32Time, "W32TimeVerifyJoinConfig");
if (NULL==pfnW32TimeVerifyJoinConfig) {
_JumpLastErrorStr(hr, vjcerror, "GetProcAddress", L"W32TimeVerifyJoinConfig");
}
_BeginTryWith(hr) {
pfnW32TimeVerifyJoinConfig();
} _TrapException(hr);
_JumpIfError(hr, vjcerror, "pfnW32TimeVerifyJoinConfig");
hr=S_OK;
vjcerror:
if (FAILED(hr)) {
HRESULT hr2=GetSystemErrorString(hr, &wszError);
if (FAILED(hr2)) {
_IgnoreError(hr2, "GetSystemErrorString");
} else {
LocalizedWPrintf2(IDS_W32TM_ERRORGENERAL_ERROR_OCCURED, L" %s\n", wszError);
}
goto error;
}
// check for vuc (verify unjoin config)
} else if (true==CheckNextArg(pca, L"vuc", NULL)) {
hr=VerifyAllArgsUsed(pca);
_JumpIfError(hr, error, "VerifyAllArgsUsed");
LocalizedWPrintfCR(IDS_W32TM_STATUS_CALLING_UNJOINCONFIG);
hmW32Time=LoadLibrary(wszDLLNAME);
if (NULL==hmW32Time) {
_JumpLastError(hr, vucerror, "LoadLibrary");
}
pfnW32TimeVerifyUnjoinConfig=(void (*)(void))GetProcAddress(hmW32Time, "W32TimeVerifyUnjoinConfig");
if (NULL==pfnW32TimeVerifyUnjoinConfig) {
_JumpLastErrorStr(hr, vucerror, "GetProcAddress", L"W32TimeVerifyJoinConfig");
}
_BeginTryWith(hr) {
pfnW32TimeVerifyUnjoinConfig();
} _TrapException(hr);
_JumpIfError(hr, vucerror, "pfnW32TimeVerifyUnjoinConfig");
hr=S_OK;
vucerror:
if (FAILED(hr)) {
HRESULT hr2=GetSystemErrorString(hr, &wszError);
if (FAILED(hr2)) {
_IgnoreError(hr2, "GetSystemErrorString");
} else {
LocalizedWPrintf2(IDS_W32TM_ERRORGENERAL_ERROR_OCCURED, L" %s\n", wszError);
}
goto error;
}
// error out appropriately
} else if (true==CheckNextArg(pca, L"qps", NULL)) {
// find out what computer to resync
if (FindArg(pca, L"computer", &wszComputer, &nArgID)) {
MarkArgUsed(pca, nArgID);
}
wszComputerDisplay=wszComputer;
if (NULL==wszComputerDisplay) {
wszComputerDisplay=L"local computer";
}
hr=VerifyAllArgsUsed(pca);
_JumpIfError(hr, error, "VerifyAllArgsUsed");
//LocalizedWPrintf2(IDS_W32TM_STATUS_CALLING_GETNETLOGONBITS_ON, L" %s.\n", wszComputerDisplay);
{
W32TIME_NTP_PROVIDER_DATA *ProviderInfo = NULL;
dwResult=W32TimeQueryNTPProviderStatus(wszComputer, 0, L"NtpClient", &ProviderInfo);
if (S_OK==dwResult) {
PrintNtpProviderData(ProviderInfo);
} else {
hr=GetSystemErrorString(HRESULT_FROM_WIN32(dwResult), &wszError);
_JumpIfError(hr, error, "GetSystemErrorString");
LocalizedWPrintf2(IDS_W32TM_ERRORGENERAL_ERROR_OCCURED, L" %s\n", wszError);
}
}
} else {
hr=VerifyAllArgsUsed(pca);
_JumpIfError(hr, error, "VerifyAllArgsUsed");
LocalizedWPrintf(IDS_W32TM_ERRORGENERAL_NOINTERFACE);
hr=E_INVALIDARG;
_JumpError(hr, error, "command line parsing");
}
hr=S_OK;
error:
if (NULL!=hmW32Time) {
FreeLibrary(hmW32Time);
}
if (NULL!=wszError) {
LocalFree(wszError);
}
return hr;
}
//--------------------------------------------------------------------
HRESULT ShowTimeZone(CmdArgs * pca) {
DWORD dwTimeZoneID;
HRESULT hr;
LPWSTR pwsz_IDS_W32TM_SIMPLESTRING_UNSPECIFIED = NULL;
LPWSTR pwsz_IDS_W32TM_TIMEZONE_CURRENT_TIMEZONE = NULL;
LPWSTR pwsz_IDS_W32TM_TIMEZONE_DAYLIGHT = NULL;
LPWSTR pwsz_IDS_W32TM_TIMEZONE_STANDARD = NULL;
LPWSTR pwsz_IDS_W32TM_TIMEZONE_UNKNOWN = NULL;
LPWSTR wszDaylightDate = NULL;
LPWSTR wszStandardDate = NULL;
LPWSTR wszTimeZoneId = NULL;
TIME_ZONE_INFORMATION tzi;
unsigned int nChars;
// Load the strings we'll need
struct LocalizedStrings {
UINT id;
LPWSTR *ppwsz;
} rgStrings[] = {
{ IDS_W32TM_SIMPLESTRING_UNSPECIFIED, &pwsz_IDS_W32TM_SIMPLESTRING_UNSPECIFIED },
{ IDS_W32TM_TIMEZONE_CURRENT_TIMEZONE, &pwsz_IDS_W32TM_TIMEZONE_CURRENT_TIMEZONE },
{ IDS_W32TM_TIMEZONE_DAYLIGHT, &pwsz_IDS_W32TM_TIMEZONE_DAYLIGHT },
{ IDS_W32TM_TIMEZONE_STANDARD, &pwsz_IDS_W32TM_TIMEZONE_STANDARD },
{ IDS_W32TM_TIMEZONE_UNKNOWN, &pwsz_IDS_W32TM_TIMEZONE_UNKNOWN }
};
for (DWORD dwIndex = 0; dwIndex < ARRAYSIZE(rgStrings); dwIndex++) {
if (!WriteMsg(FORMAT_MESSAGE_FROM_HMODULE, rgStrings[dwIndex].id, rgStrings[dwIndex].ppwsz)) {
hr = HRESULT_FROM_WIN32(GetLastError());
_JumpError(hr, error, "WriteMsg");
}
}
hr=VerifyAllArgsUsed(pca);
_JumpIfError(hr, error, "VerifyAllArgsUsed");
dwTimeZoneID=GetTimeZoneInformation(&tzi);
switch (dwTimeZoneID)
{
case TIME_ZONE_ID_DAYLIGHT: wszTimeZoneId = pwsz_IDS_W32TM_TIMEZONE_DAYLIGHT; break;
case TIME_ZONE_ID_STANDARD: wszTimeZoneId = pwsz_IDS_W32TM_TIMEZONE_STANDARD; break;
case TIME_ZONE_ID_UNKNOWN: wszTimeZoneId = pwsz_IDS_W32TM_TIMEZONE_UNKNOWN; break;
default:
hr = HRESULT_FROM_WIN32(GetLastError());
LocalizedWPrintfCR(IDS_W32TM_ERRORTIMEZONE_INVALID);
_JumpError(hr, error, "GetTimeZoneInformation")
}
// Construct a string representing the "StandardDate" field of the TimeZoneInformation:
if (0==tzi.StandardDate.wMonth) {
wszStandardDate = pwsz_IDS_W32TM_SIMPLESTRING_UNSPECIFIED;
} else if (tzi.StandardDate.wMonth>12 || tzi.StandardDate.wDay>5 ||
tzi.StandardDate.wDay<1 || tzi.StandardDate.wDayOfWeek>6) {
if (!WriteMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_W32TM_INVALID_TZ_DATE, &wszStandardDate,
tzi.StandardDate.wMonth, tzi.StandardDate.wDay, tzi.StandardDate.wDayOfWeek)) {
_JumpLastError(hr, error, "WriteMsg");
}
} else {
if (!WriteMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_W32TM_VALID_TZ_DATE, &wszStandardDate,
tzi.StandardDate.wMonth, tzi.StandardDate.wDay, tzi.StandardDate.wDayOfWeek)) {
_JumpLastError(hr, error, "WriteMsg");
}
}
// Construct a string representing the "DaylightDate" field of the TimeZoneInformation:
if (0==tzi.DaylightDate.wMonth) {
wszDaylightDate = pwsz_IDS_W32TM_SIMPLESTRING_UNSPECIFIED;
} else if (tzi.DaylightDate.wMonth>12 || tzi.DaylightDate.wDay>5 ||
tzi.DaylightDate.wDay<1 || tzi.DaylightDate.wDayOfWeek>6) {
if (!WriteMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_W32TM_INVALID_TZ_DATE, &wszDaylightDate,
tzi.DaylightDate.wMonth, tzi.DaylightDate.wDay, tzi.DaylightDate.wDayOfWeek)) {
_JumpLastError(hr, error, "WriteMsg");
}
} else {
if (!WriteMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_W32TM_VALID_TZ_DATE, &wszDaylightDate,
tzi.DaylightDate.wMonth, tzi.DaylightDate.wDay, tzi.DaylightDate.wDayOfWeek)) {
_JumpLastError(hr, error, "WriteMsg");
}
}
DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_W32TM_TIMEZONE_INFO,
wszTimeZoneId, tzi.Bias,
tzi.StandardName, tzi.StandardBias, wszStandardDate,
tzi.DaylightName, tzi.DaylightBias, wszDaylightDate);
hr=S_OK;
error:
// Free our localized strings:
for (DWORD dwIndex = 0; dwIndex < ARRAYSIZE(rgStrings); dwIndex++) {
if (NULL != *(rgStrings[dwIndex].ppwsz)) { LocalFree(*(rgStrings[dwIndex].ppwsz)); }
}
if (NULL != wszDaylightDate) {
LocalFree(wszDaylightDate);
}
if (NULL != wszStandardDate) {
LocalFree(wszStandardDate);
}
if (FAILED(hr) && E_INVALIDARG!=hr) {
WCHAR * wszError;
HRESULT hr2=GetSystemErrorString(hr, &wszError);
if (FAILED(hr2)) {
_IgnoreError(hr2, "GetSystemErrorString");
} else {
LocalizedWPrintf2(IDS_W32TM_ERRORGENERAL_ERROR_OCCURED, L" %s\n", wszError);
LocalFree(wszError);
}
}
return hr;
}
//--------------------------------------------------------------------
HRESULT PrintRegLine(IN HANDLE hOut,
IN DWORD dwValueNameOffset,
IN LPWSTR pwszValueName,
IN DWORD dwValueTypeOffset,
IN LPWSTR pwszValueType,
IN DWORD dwValueDataOffset,
IN LPWSTR pwszValueData)
{
DWORD dwCurrentOffset = 0;
HRESULT hr;
WCHAR pwszLine[1024];
WCHAR wszNULL[] = L"<NULL>";
if (NULL == pwszValueName) { pwszValueName = &wszNULL[0]; }
if (NULL == pwszValueType) { pwszValueType = &wszNULL[0]; }
if (NULL == pwszValueData) { pwszValueData = &wszNULL[0]; }
// Ensure no buffer overflow:
_Verify(1024 > dwValueDataOffset + wcslen(pwszValueData), hr, error);
dwCurrentOffset = dwValueNameOffset;
dwCurrentOffset = wsprintf(&pwszLine[0] + dwCurrentOffset, L"%s", pwszValueName);
while (dwCurrentOffset < dwValueTypeOffset) {
dwCurrentOffset += wsprintf(&pwszLine[0] + dwCurrentOffset, L" ");
}
dwCurrentOffset += wsprintf(&pwszLine[0] + dwCurrentOffset, L"%s", pwszValueType);
while (dwCurrentOffset < dwValueDataOffset) {
dwCurrentOffset += wsprintf(&pwszLine[0] + dwCurrentOffset, L" ");
}
wsprintf(&pwszLine[0] + dwCurrentOffset, L"%s\n", pwszValueData);
//
PrintStr(hOut, &pwszLine[0]);
hr = S_OK;
error:
return hr;
}
HRESULT DumpReg(CmdArgs * pca)
{
BOOL fLoggedFailure = FALSE;
DWORD dwMaxValueNameLen = 0; // Size in TCHARs.
DWORD dwMaxValueDataLen = 0; // Size in bytes.
DWORD dwNumValues = 0;
DWORD dwRetval = 0;
DWORD dwType = 0;
DWORD dwValueNameLen = 0; // Size in TCHARs.
DWORD dwValueDataLen = 0; // Size in bytes.
HANDLE hOut = NULL;
HKEY hKeyConfig = NULL;
HKEY HKLM = HKEY_LOCAL_MACHINE;
HKEY HKLMRemote = NULL;
HRESULT hr = E_FAIL;
LPWSTR pwszValueName = NULL;
LPBYTE pbValueData = NULL;
LPWSTR pwszSubkeyName = NULL;
LPWSTR pwszComputerName = NULL;
unsigned int nArgID = 0;
WCHAR rgwszKeyName[1024];
// Variables to display formatted output:
DWORD dwCurrentOffset = 0;
DWORD dwValueNameOffset = 0;
DWORD dwValueTypeOffset = 0;
DWORD dwValueDataOffset = 0;
// Localized strings:
LPWSTR pwsz_VALUENAME = NULL;
LPWSTR pwsz_VALUETYPE = NULL;
LPWSTR pwsz_VALUEDATA = NULL;
LPWSTR pwsz_REGTYPE_DWORD = NULL;
LPWSTR pwsz_REGTYPE_SZ = NULL;
LPWSTR pwsz_REGTYPE_MULTISZ = NULL;
LPWSTR pwsz_REGTYPE_EXPANDSZ = NULL;
LPWSTR pwsz_REGTYPE_UNKNOWN = NULL;
LPWSTR pwsz_REGDATA_UNPARSABLE = NULL;
// Load the strings we'll need
struct LocalizedStrings {
UINT id;
LPWSTR *ppwsz;
} rgStrings[] = {
{ IDS_W32TM_VALUENAME, &pwsz_VALUENAME },
{ IDS_W32TM_VALUETYPE, &pwsz_VALUETYPE },
{ IDS_W32TM_VALUEDATA, &pwsz_VALUEDATA },
{ IDS_W32TM_REGTYPE_DWORD, &pwsz_REGTYPE_DWORD },
{ IDS_W32TM_REGTYPE_SZ, &pwsz_REGTYPE_SZ },
{ IDS_W32TM_REGTYPE_MULTISZ, &pwsz_REGTYPE_MULTISZ },
{ IDS_W32TM_REGTYPE_EXPANDSZ, &pwsz_REGTYPE_EXPANDSZ },
{ IDS_W32TM_REGTYPE_UNKNOWN, &pwsz_REGTYPE_UNKNOWN },
{ IDS_W32TM_REGDATA_UNPARSABLE, &pwsz_REGDATA_UNPARSABLE }
};
for (DWORD dwIndex = 0; dwIndex < ARRAYSIZE(rgStrings); dwIndex++) {
if (!WriteMsg(FORMAT_MESSAGE_FROM_HMODULE, rgStrings[dwIndex].id, rgStrings[dwIndex].ppwsz)) {
hr = HRESULT_FROM_WIN32(GetLastError());
_JumpError(hr, error, "WriteMsg");
}
}
dwCurrentOffset = wsprintf(&rgwszKeyName[0], wszW32TimeRegKeyRoot);
if (true==FindArg(pca, L"subkey", &pwszSubkeyName, &nArgID)) {
MarkArgUsed(pca, nArgID);
if (NULL == pwszSubkeyName) {
LocalizedWPrintfCR(IDS_W32TM_ERRORDUMPREG_NO_SUBKEY_SPECIFIED);
fLoggedFailure = TRUE;
hr = E_INVALIDARG;
_JumpError(hr, error, "command line parsing");
}
dwCurrentOffset += wsprintf(&rgwszKeyName[0] + dwCurrentOffset, L"\\");
wsprintf(&rgwszKeyName[0] + dwCurrentOffset, pwszSubkeyName);
}
if (true==FindArg(pca, L"computer", &pwszComputerName, &nArgID)) {
MarkArgUsed(pca, nArgID);
dwRetval = RegConnectRegistry(pwszComputerName, HKEY_LOCAL_MACHINE, &HKLMRemote);
if (ERROR_SUCCESS != dwRetval) {
hr = HRESULT_FROM_WIN32(dwRetval);
_JumpErrorStr(hr, error, "RegConnectRegistry", L"HKEY_LOCAL_MACHINE");
}
HKLM = HKLMRemote;
}
hr = VerifyAllArgsUsed(pca);
_JumpIfError(hr, error, "VerifyAllArgsUsed");
dwRetval = RegOpenKeyEx(HKLM, rgwszKeyName, 0, KEY_QUERY_VALUE, &hKeyConfig);
if (ERROR_SUCCESS != dwRetval) {
hr = HRESULT_FROM_WIN32(dwRetval);
_JumpErrorStr(hr, error, "RegOpenKeyEx", rgwszKeyName);
}
dwRetval = RegQueryInfoKey
(hKeyConfig,
NULL, // class buffer
NULL, // size of class buffer
NULL, // reserved
NULL, // number of subkeys
NULL, // longest subkey name
NULL, // longest class string
&dwNumValues, // number of value entries
&dwMaxValueNameLen, // longest value name
&dwMaxValueDataLen, // longest value data
NULL,
NULL
);
if (ERROR_SUCCESS != dwRetval) {
hr = HRESULT_FROM_WIN32(dwRetval);
_JumpErrorStr(hr, error, "RegQueryInfoKey", rgwszKeyName);
} else if (0 == dwNumValues) {
hr = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
_JumpErrorStr(hr, error, "RegQueryInfoKey", rgwszKeyName);
}
dwMaxValueNameLen += sizeof(WCHAR); // Include space for NULL character
pwszValueName = (LPWSTR)LocalAlloc(LPTR, dwMaxValueNameLen * sizeof(WCHAR));
_JumpIfOutOfMemory(hr, error, pwszValueName);
pbValueData = (LPBYTE)LocalAlloc(LPTR, dwMaxValueDataLen);
_JumpIfOutOfMemory(hr, error, pbValueData);
dwValueNameOffset = 0;
dwValueTypeOffset = dwValueNameOffset + dwMaxValueNameLen + 3;
dwValueDataOffset += dwValueTypeOffset + 20;
// Print table header:
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (INVALID_HANDLE_VALUE==hOut) {
_JumpLastError(hr, error, "GetStdHandle");
}
PrintStr(hOut, L"\n");
PrintRegLine(hOut, dwValueNameOffset, pwsz_VALUENAME, dwValueTypeOffset, pwsz_VALUETYPE, dwValueDataOffset, pwsz_VALUEDATA);
// Next line:
dwCurrentOffset = dwValueNameOffset;
for (DWORD dwIndex = dwCurrentOffset; dwIndex < (dwValueDataOffset + (dwMaxValueDataLen / 2)); dwIndex++) {
PrintStr(hOut, L"-");
}
PrintStr(hOut, L"\n\n");
for (DWORD dwIndex = 0; dwIndex < dwNumValues; dwIndex++) {
dwValueNameLen = dwMaxValueNameLen;
dwValueDataLen = dwMaxValueDataLen;
memset(reinterpret_cast<LPBYTE>(pwszValueName), 0, dwMaxValueNameLen * sizeof(WCHAR));
memset(pbValueData, 0, dwMaxValueDataLen);
dwRetval = RegEnumValue
(hKeyConfig, // handle to key to query
dwIndex, // index of value to query
pwszValueName, // value buffer
&dwValueNameLen, // size of value buffer (in TCHARs)
NULL, // reserved
&dwType, // type buffer
pbValueData, // data buffer
&dwValueDataLen // size of data buffer
);
if (ERROR_SUCCESS != dwRetval) {
hr = HRESULT_FROM_WIN32(dwRetval);
_JumpErrorStr(hr, error, "RegEnumValue", wszW32TimeRegKeyConfig);
}
_Verify(dwValueNameLen <= dwMaxValueNameLen, hr, error);
_Verify(dwValueDataLen <= dwMaxValueDataLen, hr, error);
{
LPWSTR pwszRegType = NULL;
LPWSTR pwszRegData = NULL;
switch (dwType) {
case REG_DWORD:
{
WCHAR rgwszDwordData[20];
_ltow(*(reinterpret_cast<long *>(pbValueData)), rgwszDwordData, 10);
pwszRegType = pwsz_REGTYPE_DWORD;
pwszRegData = &rgwszDwordData[0];
}
break;
case REG_MULTI_SZ:
{
WCHAR wszDelimiter[] = { L'\0', L'\0', L'\0' };
WCHAR rgwszMultiSzData[1024] = { L'\0' };
LPWSTR pwsz;
dwCurrentOffset = 0;
for (pwsz = (LPWSTR)pbValueData; L'\0' != *pwsz; pwsz += wcslen(pwsz)+1) {
dwCurrentOffset += wsprintf(&rgwszMultiSzData[0] + dwCurrentOffset, wszDelimiter);
dwCurrentOffset += wsprintf(&rgwszMultiSzData[0] + dwCurrentOffset, pwsz);
wszDelimiter[0] = L','; wszDelimiter[1] = L' ';
}
pwszRegType = pwsz_REGTYPE_MULTISZ;
pwszRegData = &rgwszMultiSzData[0];
}
break;
case REG_EXPAND_SZ:
{
pwszRegType = pwsz_REGTYPE_EXPANDSZ;
pwszRegData = reinterpret_cast<WCHAR *>(pbValueData);
}
break;
case REG_SZ:
{
pwszRegType = pwsz_REGTYPE_SZ;
pwszRegData = reinterpret_cast<WCHAR *>(pbValueData);
}
break;
default:
// Unrecognized reg type...
pwszRegType = pwsz_REGTYPE_UNKNOWN;
pwszRegData = pwsz_REGDATA_UNPARSABLE;
}
PrintRegLine(hOut, dwValueNameOffset, pwszValueName, dwValueTypeOffset, pwszRegType, dwValueDataOffset, pwszRegData);
}
}
PrintStr(hOut, L"\n");
hr = S_OK;
error:
// Free our localized strings:
for (DWORD dwIndex = 0; dwIndex < ARRAYSIZE(rgStrings); dwIndex++) {
if (NULL != *(rgStrings[dwIndex].ppwsz)) { LocalFree(*(rgStrings[dwIndex].ppwsz)); }
}
if (NULL != hKeyConfig) { RegCloseKey(hKeyConfig); }
if (NULL != HKLMRemote) { RegCloseKey(HKLMRemote); }
if (NULL != pwszValueName) { LocalFree(pwszValueName); }
if (NULL != pbValueData) { LocalFree(pbValueData); }
if (FAILED(hr) && !fLoggedFailure) {
WCHAR * wszError;
HRESULT hr2=GetSystemErrorString(hr, &wszError);
if (FAILED(hr2)) {
_IgnoreError(hr2, "GetSystemErrorString");
} else {
LocalizedWPrintf2(IDS_W32TM_ERRORGENERAL_ERROR_OCCURED, L" %s\n", wszError);
LocalFree(wszError);
}
}
return hr;
}