/-------------------------------------------------------------------- // 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 /* 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-_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; nnNextArg!=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