//depot/Lab03_N/DS/security/services/w32time/w32tm/OtherCmds.cpp#16 - edit change 15254 (text) //-------------------------------------------------------------------- // OtherCmds-implementation // Copyright (C) Microsoft Corporation, 1999 // // Created by: Louis Thomas (louisth), 2-17-00 // // Other useful w32tm commands // #include "pch.h" // precompiled headers #include //-------------------------------------------------------------------- //#################################################################### //## //## 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); } MODULEPRIVATE HRESULT my_wcstoul_safe(const WCHAR *wsz, ULONG ulMin, ULONG ulMax, ULONG *pulResult) { HRESULT hr; ULONG ulResult; WCHAR *wszLast; if (L'\0' == *wsz) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); _JumpError(hr, error, "my_wcstoul_safe: empty string is not valid"); } ulResult = wcstoul(wsz, &wszLast, 0); // Ensure that we were able to parse the whole string: if (wsz+wcslen(wsz) != wszLast) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); _JumpError(hr, error, "wcstoul"); } // Ensure that we lie within the bounds specified by the caler: if (!((ulMin <= ulResult) && (ulResult <= ulMax))) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); _JumpError(hr, error, "my_wcstoul_safe: result not within bounds"); } *pulResult = ulResult; hr = S_OK; error: return hr; } //#################################################################### //-------------------------------------------------------------------- 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, ...) { HRESULT hr; WCHAR wszBuf[1024]; va_list vlArgs; va_start(vlArgs, wszFormat); // print the formatted data to our buffer: hr=StringCchVPrintf(wszBuf, ARRAYSIZE(wszBuf), wszFormat, vlArgs); va_end(vlArgs); if (SUCCEEDED(hr)) { // only print the string if our vprintf was successful: hr = PrintStr(hOut, wszBuf); } return hr; } //-------------------------------------------------------------------- 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) { DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_W32TM_OTHERCMD_HELP); } //-------------------------------------------------------------------- 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=0; NtTimeEpoch teNow; // must be cleaned up 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 NT time (10^-7 seconds) bLargePhaseOffset=true; } hr=VerifyAllArgsUsed(pca); _JumpIfError(hr, error, "VerifyAllArgsUsed"); if (!bManualPeerList && !bSyncFromFlags && !bUpdate && !bLocalClockDispersion && !bReliable && !bLargePhaseOffset) { LocalizedWPrintfCR(IDS_W32TM_ERRORCONFIG_NO_CHANGE_SPECIFIED); hr=E_INVALIDARG; _JumpError(hr, error, "command line parsing"); } // make registry changes if (bManualPeerList || bSyncFromFlags || bLocalClockDispersion || bReliable || bLargePhaseOffset) { // 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 || bReliable || bLargePhaseOffset) { dwRetval=RegOpenKey(hkLMRemote, wszW32TimeRegKeyConfig, &hkW32TimeConfig); if (ERROR_SUCCESS!=dwRetval) { hr=HRESULT_FROM_WIN32(dwRetval); _JumpError(hr, error, "RegOpenKey"); } if (bLocalClockDispersion) { dwRetval=RegSetValueEx(hkW32TimeConfig, wszW32TimeRegValueLocalClockDispersion, 0, REG_DWORD, (BYTE *)&dwLocalClockDispersion, sizeof(dwLocalClockDispersion)); if (ERROR_SUCCESS!=dwRetval) { hr=HRESULT_FROM_WIN32(dwRetval); _JumpError(hr, error, "RegSetValueEx"); } } if (bReliable) { dwRetval=RegSetValueEx(hkW32TimeConfig, wszW32TimeRegValueAnnounceFlags, 0, REG_DWORD, (BYTE *)&dwAnnounceFlags, sizeof(dwAnnounceFlags)); if (ERROR_SUCCESS!=dwRetval) { hr=HRESULT_FROM_WIN32(dwRetval); _JumpError(hr, error, "RegSetValueEx"); } } if (bLargePhaseOffset) { dwRetval=RegSetValueEx(hkW32TimeConfig, wszW32TimeRegValueLargePhaseOffset, 0, REG_DWORD, (BYTE *)&dwLargePhaseOffset, sizeof(dwLargePhaseOffset)); 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; // 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; LPWSTR pwszCurrent; LPWSTR pwszEnd; WCHAR pwszLine[1024]; WCHAR wszNULL[] = L""; if (NULL == pwszValueName) { pwszValueName = &wszNULL[0]; } if (NULL == pwszValueType) { pwszValueType = &wszNULL[0]; } if (NULL == pwszValueData) { pwszValueData = &wszNULL[0]; } pwszEnd = pwszLine + ARRAYSIZE(pwszLine); // point to the end of the line buffer pwszCurrent = &pwszLine[0]; // point to the beginning of the line buffer // // Use the safe string functions to populate the line buffer // hr = StringCchCopy(pwszCurrent, pwszEnd-pwszCurrent, pwszValueName); _JumpIfError(hr, error, "StringCchCopy"); pwszCurrent += wcslen(pwszCurrent); // Insert enough spaces to align the "type" field with the type offset for (DWORD dwIndex = pwszCurrent-pwszLine; dwIndex < dwValueTypeOffset; dwIndex++) { hr = StringCchCopy(pwszCurrent, pwszEnd-pwszCurrent, L" "); _JumpIfError(hr, error, "StringCchCopy"); pwszCurrent++; } hr = StringCchCopy(pwszCurrent, pwszEnd-pwszCurrent, pwszValueType); _JumpIfError(hr, error, "StringCchCopy"); pwszCurrent += wcslen(pwszCurrent); // Insert enoughs spaces to align the "data" field with the data offset for (DWORD dwIndex = pwszCurrent-pwszLine; dwIndex < dwValueDataOffset; dwIndex++) { hr = StringCchCopy(pwszCurrent, pwszEnd-pwszCurrent, L" "); _JumpIfError(hr, error, "StringCchCopy"); pwszCurrent++; } hr = StringCchCopy(pwszCurrent, pwszEnd-pwszCurrent, pwszValueData); _JumpIfError(hr, error, "StringCchCopy"); pwszCurrent += wcslen(pwszCurrent); hr = StringCchCopy(pwszCurrent, pwszEnd-pwszCurrent, L"\n"); _JumpIfError(hr, error, "StringCchCopy"); // Finally, display the reg line PrintStr(hOut, &pwszLine[0]); hr = S_OK; error: return hr; } HRESULT DumpReg(CmdArgs * pca) { BOOL fFreeRegData = FALSE; // Used to indicate whether we've dymanically allocated pwszRegData 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; LPWSTR pwszRegType = NULL; LPWSTR pwszRegData = 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_BINARY = 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_BINARY, &pwsz_REGTYPE_BINARY }, { 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"); } } hr = StringCchCopy(&rgwszKeyName[0], ARRAYSIZE(rgwszKeyName), wszW32TimeRegKeyRoot); _JumpIfError(hr, error, "StringCchCopy"); 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"); } hr = StringCchCat(&rgwszKeyName[0], ARRAYSIZE(rgwszKeyName), L"\\"); _JumpIfError(hr, error, "StringCchCopy"); hr = StringCchCat(&rgwszKeyName[0], ARRAYSIZE(rgwszKeyName), pwszSubkeyName); _JumpIfError(hr, error, "StringCchCopy"); } 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 + wcslen(pwsz_VALUEDATA) + 3); dwIndex++) { PrintStr(hOut, L"-"); } PrintStr(hOut, L"\n\n"); for (DWORD dwIndex = 0; dwIndex < dwNumValues; dwIndex++) { dwValueNameLen = dwMaxValueNameLen; dwValueDataLen = dwMaxValueDataLen; memset(reinterpret_cast(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); { switch (dwType) { case REG_DWORD: { WCHAR rgwszDwordData[20]; // Ensure that the returned data buffer is large enough to contain a DWORD: _Verify(dwValueDataLen >= sizeof(long), hr, error); _ltow(*(reinterpret_cast(pbValueData)), rgwszDwordData, 10); pwszRegType = pwsz_REGTYPE_DWORD; pwszRegData = &rgwszDwordData[0]; } break; case REG_MULTI_SZ: { DWORD cbMultiSzData = 0; WCHAR wszDelimiter[] = { L'\0', L'\0', L'\0' }; LPWSTR pwsz; // calculate the size of the string buffer needed to contain the string data for this MULTI_SZ for (pwsz = (LPWSTR)pbValueData; L'\0' != *pwsz; pwsz += wcslen(pwsz)+1) { cbMultiSzData += sizeof(WCHAR)*(wcslen(pwsz)+1); cbMultiSzData += sizeof(WCHAR)*2; // include space for delimiter } cbMultiSzData += sizeof(WCHAR); // include space for NULL-termination char // allocate the buffer pwszRegData = (LPWSTR)LocalAlloc(LPTR, cbMultiSzData); _JumpIfOutOfMemory(hr, error, pwszRegData); fFreeRegData = TRUE; for (pwsz = (LPWSTR)pbValueData; L'\0' != *pwsz; pwsz += wcslen(pwsz)+1) { hr = StringCbCat(pwszRegData, cbMultiSzData, wszDelimiter); _JumpIfError(hr, error, "StringCbCat"); hr = StringCbCat(pwszRegData, cbMultiSzData, pwsz); _JumpIfError(hr, error, "StringCbCat"); wszDelimiter[0] = L','; wszDelimiter[1] = L' '; } pwszRegType = pwsz_REGTYPE_MULTISZ; } break; case REG_EXPAND_SZ: { pwszRegType = pwsz_REGTYPE_EXPANDSZ; pwszRegData = reinterpret_cast(pbValueData); } break; case REG_SZ: { pwszRegType = pwsz_REGTYPE_SZ; pwszRegData = reinterpret_cast(pbValueData); } break; case REG_BINARY: { DWORD ccRegData = (2*dwValueDataLen); pwszRegType = pwsz_REGTYPE_BINARY; // Allocate 2 characters per each byte of the binary data. pwszRegData = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*(ccRegData+1)); _JumpIfOutOfMemory(hr, error, pwszRegData); fFreeRegData = TRUE; LPBYTE pb = pbValueData; for (LPWSTR pwsz = pwszRegData; pwsz < pwsz+ccRegData; ) { hr = StringCchPrintf(pwsz, ccRegData+1, L"%02X", *pb); _JumpIfError(hr, error, "StringCchPrintf"); pwsz += 2; ccRegData -= 2; pb++; } } break; default: // Unrecognized reg type... pwszRegType = pwsz_REGTYPE_UNKNOWN; pwszRegData = pwsz_REGDATA_UNPARSABLE; } PrintRegLine(hOut, dwValueNameOffset, pwszValueName, dwValueTypeOffset, pwszRegType, dwValueDataOffset, pwszRegData); if (fFreeRegData) { LocalFree(pwszRegData); fFreeRegData = FALSE; } pwszRegData = NULL; } } 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 (fFreeRegData && NULL != pwszRegData) { LocalFree(pwszRegData); } 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; }