Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

479 lines
16 KiB

  1. //--------------------------------------------------------------------
  2. // PingLib - implementation
  3. // Copyright (C) Microsoft Corporation, 1999
  4. //
  5. // Created by: Louis Thomas (louisth), 10-8-99
  6. //
  7. // Various ways of pinging a server
  8. //
  9. #include "pch.h" // precompiled headers
  10. #include <ipexport.h>
  11. #include <icmpapi.h>
  12. #include <DcInfo.h>
  13. #include "NtpBase.h"
  14. #include "EndianSwap.inl"
  15. //####################################################################
  16. // OLD CODE
  17. #if 0
  18. //--------------------------------------------------------------------
  19. MODULEPRIVATE HRESULT LookupServer(IN WCHAR * wszServerName, OUT sockaddr * psaOut, IN int nAddrSize) {
  20. HRESULT hr;
  21. DWORD dwDataLen;
  22. SOCKET_ADDRESS * psaFound;
  23. // pointers that must be cleaned up
  24. HANDLE hSearch=INVALID_HANDLE_VALUE;
  25. WSAQUERYSETW * pqsResult=NULL;
  26. DebugWPrintf1(L"Looking up server \"%s\":\n", wszServerName);
  27. // initialize the search
  28. // const static GUID guidHostAddressByName = SVCID_INET_HOSTADDRBYNAME;
  29. AFPROTOCOLS apInetUdp={AF_INET, IPPROTO_UDP};
  30. GUID guidNtp=SVCID_NTP_UDP;
  31. WSAQUERYSETW qsSearch;
  32. ZeroMemory(&qsSearch, sizeof(qsSearch));
  33. qsSearch.dwSize=sizeof(qsSearch);
  34. qsSearch.lpszServiceInstanceName=wszServerName;
  35. qsSearch.lpServiceClassId=&guidNtp;
  36. qsSearch.dwNameSpace=NS_ALL;
  37. qsSearch.dwNumberOfProtocols=1;
  38. qsSearch.lpafpProtocols=&apInetUdp;
  39. if (SOCKET_ERROR==WSALookupServiceBegin(&qsSearch, LUP_RETURN_ADDR/*flags*/, &hSearch)) {
  40. _JumpLastError(hr, error, "WSALookupServiceBegin");
  41. }
  42. // get the buffer size for the first value
  43. dwDataLen=1;
  44. _Verify(SOCKET_ERROR==WSALookupServiceNext(hSearch, LUP_RETURN_ADDR/*flags*/, &dwDataLen, &qsSearch), hr, error);
  45. if (WSAEFAULT!=GetLastError()) {
  46. _JumpLastError(hr, error, "WSALookupServiceNext");
  47. }
  48. // allocate the buffer
  49. pqsResult=reinterpret_cast<WSAQUERYSETW *>(LocalAlloc(LMEM_FIXED, dwDataLen));
  50. _JumpIfOutOfMemory(hr, error, pqsResult);
  51. // retrieve the first value
  52. if (SOCKET_ERROR==WSALookupServiceNext(hSearch, LUP_RETURN_ADDR/*flags*/, &dwDataLen, pqsResult)) {
  53. _JumpLastError(hr, error, "WSALookupServiceNext");
  54. }
  55. _Verify(pqsResult->dwNumberOfCsAddrs>0, hr, error);
  56. if (pqsResult->dwNumberOfCsAddrs>1) {
  57. DebugWPrintf1(L"WSALookupServiceNextW returned %d addresses. Using first one.\n", pqsResult->dwNumberOfCsAddrs);
  58. }
  59. psaFound=&(pqsResult->lpcsaBuffer[0].RemoteAddr);
  60. _Verify(nAddrSize==psaFound->iSockaddrLength, hr, error);
  61. *psaOut=*(psaFound->lpSockaddr);
  62. DumpSockaddr(psaOut, nAddrSize);
  63. hr=S_OK;
  64. error:
  65. if (NULL!=pqsResult) {
  66. LocalFree(pqsResult);
  67. }
  68. if (INVALID_HANDLE_VALUE!=hSearch) {
  69. if (SOCKET_ERROR==WSALookupServiceEnd(hSearch)) {
  70. _IgnoreLastError("WSALookupServiceEnd");
  71. }
  72. }
  73. return hr;
  74. }
  75. //--------------------------------------------------------------------
  76. MODULEPRIVATE HRESULT GetSample(WCHAR * wszServerName, TpcGetSamplesArgs * ptgsa) {
  77. HRESULT hr;
  78. NtpPacket npPacket;
  79. NtTimeEpoch teDestinationTimestamp;
  80. unsigned int nIpAddrs;
  81. // must be cleaned up
  82. in_addr * rgiaLocalIpAddrs=NULL;
  83. in_addr * rgiaRemoteIpAddrs=NULL;
  84. hr=MyGetIpAddrs(wszServerName, &rgiaLocalIpAddrs, &rgiaRemoteIpAddrs, &nIpAddrs, NULL);
  85. _JumpIfError(hr, error, "MyGetIpAddrs");
  86. _Verify(0!=nIpAddrs, hr, error);
  87. hr=MyNtpPing(&(rgiaRemoteIpAddrs[0]), 500, &npPacket, &teDestinationTimestamp);
  88. _JumpIfError(hr, error, "MyNtpPing");
  89. {
  90. NtTimeEpoch teOriginateTimestamp=NtTimeEpochFromNtpTimeEpoch(npPacket.teOriginateTimestamp);
  91. NtTimeEpoch teReceiveTimestamp=NtTimeEpochFromNtpTimeEpoch(npPacket.teReceiveTimestamp);
  92. NtTimeEpoch teTransmitTimestamp=NtTimeEpochFromNtpTimeEpoch(npPacket.teTransmitTimestamp);
  93. NtTimeOffset toRoundtripDelay=
  94. (teDestinationTimestamp-teOriginateTimestamp)
  95. - (teTransmitTimestamp-teReceiveTimestamp);
  96. NtTimeOffset toLocalClockOffset=
  97. (teReceiveTimestamp-teOriginateTimestamp)
  98. + (teTransmitTimestamp-teDestinationTimestamp);
  99. toLocalClockOffset/=2;
  100. NtTimePeriod tpClockTickSize;
  101. g_npstate.tpsc.pfnGetTimeSysInfo(TSI_ClockTickSize, &tpClockTickSize.qw);
  102. TimeSample * pts=(TimeSample *)ptgsa->pbSampleBuf;
  103. pts->dwSize=sizeof(TimeSample);
  104. pts->dwRefid=npPacket.refid.value;
  105. pts->toOffset=toLocalClockOffset.qw;
  106. pts->toDelay=(toRoundtripDelay
  107. +NtTimeOffsetFromNtpTimeOffset(npPacket.toRootDelay)
  108. ).qw;
  109. pts->tpDispersion=(tpClockTickSize
  110. +NtpConst::timesMaxSkewRate(abs(teDestinationTimestamp-teOriginateTimestamp))
  111. +NtTimePeriodFromNtpTimePeriod(npPacket.tpRootDispersion)
  112. ).qw;
  113. g_npstate.tpsc.pfnGetTimeSysInfo(TSI_TickCount, &(pts->nSysTickCount));
  114. g_npstate.tpsc.pfnGetTimeSysInfo(TSI_PhaseOffset, &(pts->nSysPhaseOffset));
  115. pts->nStratum=npPacket.nStratum;
  116. pts->nLeapFlags=npPacket.nLeapIndicator;
  117. ptgsa->dwSamplesAvailable=1;
  118. ptgsa->dwSamplesReturned=1;
  119. }
  120. hr=S_OK;
  121. error:
  122. if (NULL!=rgiaLocalIpAddrs) {
  123. LocalFree(rgiaLocalIpAddrs);
  124. }
  125. if (NULL!=rgiaRemoteIpAddrs) {
  126. LocalFree(rgiaRemoteIpAddrs);
  127. }
  128. return hr;
  129. }
  130. #endif
  131. //####################################################################
  132. // module public
  133. //--------------------------------------------------------------------
  134. HRESULT MyIcmpPing(in_addr * piaTarget, DWORD dwTimeout, DWORD * pdwResponseTime) {
  135. HRESULT hr;
  136. IPAddr ipaddrDest=piaTarget->S_un.S_addr;
  137. BYTE rgbData[8]={'a','b','c','d','e','f','g','h'};
  138. BYTE rgbResponse[1024];
  139. DWORD dwDataSize;
  140. // must be cleaned up
  141. HANDLE hIcmp=NULL;
  142. // open a handle for icmp access
  143. hIcmp=IcmpCreateFile();
  144. if (NULL==hIcmp) {
  145. _JumpLastError(hr, error, "IcmpCreateFile");
  146. }
  147. // ping
  148. ZeroMemory(rgbResponse, sizeof(rgbResponse));
  149. dwDataSize=IcmpSendEcho(hIcmp, ipaddrDest, rgbData, 8, NULL, rgbResponse, sizeof(rgbResponse), dwTimeout);
  150. if (0==dwDataSize) {
  151. _JumpLastError(hr, error, "IcmpSendEcho");
  152. }
  153. *pdwResponseTime=((icmp_echo_reply *)rgbResponse)->RoundTripTime;
  154. hr=S_OK;
  155. error:
  156. if (NULL!=hIcmp) {
  157. IcmpCloseHandle(hIcmp);
  158. }
  159. return hr;
  160. }
  161. //--------------------------------------------------------------------
  162. HRESULT MyNtpPing(in_addr * piaTarget, DWORD dwTimeout, NtpPacket * pnpPacket, NtTimeEpoch * pteDestinationTimestamp) {
  163. HRESULT hr;
  164. sockaddr saServer;
  165. int nBytesRecvd;
  166. DWORD dwWaitResult;
  167. // must be cleaned up
  168. SOCKET sTest=INVALID_SOCKET;
  169. HANDLE hDataAvailEvent=NULL;
  170. // create a socket
  171. sTest=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  172. if (INVALID_SOCKET==sTest) {
  173. _JumpLastError(hr, error, "socket");
  174. }
  175. // fix the destination address
  176. {
  177. sockaddr_in & saiServer=*(sockaddr_in *)(&saServer);
  178. saiServer.sin_port=EndianSwap((unsigned __int16)NtpConst::nPort);
  179. saiServer.sin_family=AF_INET;
  180. saiServer.sin_addr.S_un.S_addr=piaTarget->S_un.S_addr;
  181. }
  182. // connect the socket to the peer
  183. if (SOCKET_ERROR==connect(sTest, &saServer, sizeof(saServer))) {
  184. _JumpLastError(hr, error, "connect");
  185. }
  186. // send an NTP packet
  187. //DebugWPrintf1(L"Sending %d byte SNTP packet.\n", sizeof(NtpPacket));
  188. ZeroMemory(pnpPacket, sizeof(NtpPacket));
  189. pnpPacket->nMode=e_Client;
  190. pnpPacket->nVersionNumber=1;
  191. pnpPacket->teTransmitTimestamp=NtpTimeEpochFromNtTimeEpoch(GetCurrentSystemNtTimeEpoch());
  192. if (SOCKET_ERROR==send(sTest, reinterpret_cast<char *>(pnpPacket), sizeof(NtpPacket), 0/*flags*/)) {
  193. _JumpLastError(hr, error, "send");
  194. }
  195. // create the data available event
  196. hDataAvailEvent=CreateEvent(NULL /*security*/, FALSE /*auto-reset*/, FALSE /*nonsignaled*/, NULL /*name*/);
  197. if (NULL==hDataAvailEvent) {
  198. _JumpLastError(hr, error, "CreateEvent");
  199. }
  200. // bind the event to this socket
  201. if (SOCKET_ERROR==WSAEventSelect(sTest, hDataAvailEvent, FD_READ)) {
  202. _JumpLastError(hr, error, "WSAEventSelect");
  203. }
  204. // listen on the socket
  205. //DebugWPrintf1(L"Waiting for response for %ums...\n", dwTimeout);
  206. dwWaitResult=WaitForSingleObject(hDataAvailEvent, dwTimeout);
  207. if (WAIT_FAILED==dwWaitResult) {
  208. _JumpLastError(hr, error, "WaitForSingleObject");
  209. } else if (WAIT_TIMEOUT==dwWaitResult) {
  210. //DebugWPrintf0(L"No response.\n");
  211. hr=HRESULT_FROM_WIN32(ERROR_TIMEOUT);
  212. _JumpError(hr, error, "WaitForSingleObject");
  213. } else {
  214. // retrieve the data
  215. nBytesRecvd=recv(sTest, reinterpret_cast<char *>(pnpPacket), sizeof(NtpPacket), 0/*flags*/);
  216. *pteDestinationTimestamp=GetCurrentSystemNtTimeEpoch();
  217. if (SOCKET_ERROR==nBytesRecvd) {
  218. _JumpLastError(hr, error, "recv");
  219. }
  220. //DebugWPrintf2(L"Recvd %d of %d bytes.\n", nBytesRecvd, sizeof(NtpPacket));
  221. //DumpNtpPacket(&npPacket,teDestinationTimestamp);
  222. }
  223. // done
  224. hr=S_OK;
  225. error:
  226. if (INVALID_SOCKET!=sTest) {
  227. if (SOCKET_ERROR==closesocket(sTest)) {
  228. _IgnoreLastError("closesocket");
  229. }
  230. }
  231. if (NULL!=hDataAvailEvent) {
  232. CloseHandle(hDataAvailEvent);
  233. }
  234. return hr;
  235. }
  236. //--------------------------------------------------------------------
  237. HRESULT MyGetIpAddrs(const WCHAR * wszDnsName, in_addr ** prgiaLocalIpAddrs, in_addr ** prgiaRemoteIpAddrs, unsigned int *pnIpAddrs, bool * pbRetry) {
  238. AFPROTOCOLS apInetUdp = { AF_INET, IPPROTO_UDP };
  239. bool bRetry = FALSE;
  240. DWORD dwDataLen;
  241. GUID guidNtp = SVCID_NTP_UDP;
  242. HRESULT hr;
  243. HANDLE hSearch = INVALID_HANDLE_VALUE;
  244. in_addr *rgiaLocalIpAddrs = NULL;
  245. in_addr *rgiaRemoteIpAddrs = NULL;
  246. WSAQUERYSETW qsSearch;
  247. WSAQUERYSETW *pqsResult = NULL;
  248. ZeroMemory(&qsSearch, sizeof(qsSearch));
  249. // initialize the search
  250. qsSearch.dwSize = sizeof(qsSearch);
  251. qsSearch.lpszServiceInstanceName = const_cast<WCHAR *>(wszDnsName);
  252. qsSearch.lpServiceClassId = &guidNtp;
  253. qsSearch.dwNameSpace = NS_ALL;
  254. qsSearch.dwNumberOfProtocols = 1;
  255. qsSearch.lpafpProtocols = &apInetUdp;
  256. // begin the search
  257. if (SOCKET_ERROR == WSALookupServiceBegin(&qsSearch, LUP_RETURN_ADDR/*flags*/, &hSearch)) {
  258. hr = HRESULT_FROM_WIN32(WSAGetLastError());
  259. _JumpError(hr, error, "WSALookupServiceBegin");
  260. }
  261. // retrieve the result set
  262. dwDataLen = 5*1024;
  263. pqsResult = (WSAQUERYSETW *)LocalAlloc(LPTR, dwDataLen);
  264. _JumpIfOutOfMemory(hr, error, pqsResult);
  265. if (SOCKET_ERROR == WSALookupServiceNext(hSearch, LUP_RETURN_ADDR/*flags*/, &dwDataLen, pqsResult)) {
  266. hr = HRESULT_FROM_WIN32(WSAGetLastError());
  267. _JumpError(hr, error, "WSALookupServiceNext");
  268. }
  269. _Verify(0 != pqsResult->dwNumberOfCsAddrs, hr, error);
  270. // allocate room for the IP addresses
  271. rgiaLocalIpAddrs = (in_addr *)LocalAlloc(LPTR, sizeof(in_addr) * pqsResult->dwNumberOfCsAddrs);
  272. _JumpIfOutOfMemory(hr, error, rgiaLocalIpAddrs);
  273. rgiaRemoteIpAddrs = (in_addr *)LocalAlloc(LPTR, sizeof(in_addr) * pqsResult->dwNumberOfCsAddrs);
  274. _JumpIfOutOfMemory(hr, error, rgiaRemoteIpAddrs);
  275. // copy the IP addresses
  276. for (unsigned int nIndex = 0; nIndex < pqsResult->dwNumberOfCsAddrs; nIndex++) {
  277. // copy local
  278. _Verify(sizeof(sockaddr) == pqsResult->lpcsaBuffer[nIndex].LocalAddr.iSockaddrLength, hr, error);
  279. _Verify(AF_INET == pqsResult->lpcsaBuffer[nIndex].LocalAddr.lpSockaddr->sa_family, hr, error);
  280. rgiaLocalIpAddrs[nIndex].S_un.S_addr = ((sockaddr_in *)(pqsResult->lpcsaBuffer[nIndex].LocalAddr.lpSockaddr))->sin_addr.S_un.S_addr;
  281. // copy remote
  282. _Verify(sizeof(sockaddr) == pqsResult->lpcsaBuffer[nIndex].RemoteAddr.iSockaddrLength, hr, error);
  283. _Verify(AF_INET == pqsResult->lpcsaBuffer[nIndex].RemoteAddr.lpSockaddr->sa_family, hr, error);
  284. rgiaRemoteIpAddrs[nIndex].S_un.S_addr = ((sockaddr_in *)(pqsResult->lpcsaBuffer[nIndex].RemoteAddr.lpSockaddr))->sin_addr.S_un.S_addr;
  285. }
  286. // Assign out params:
  287. if (NULL != prgiaLocalIpAddrs) { *prgiaLocalIpAddrs = rgiaLocalIpAddrs; }
  288. if (NULL != prgiaRemoteIpAddrs) { *prgiaRemoteIpAddrs = rgiaRemoteIpAddrs; }
  289. if (NULL != pbRetry) { *pbRetry = bRetry; }
  290. if (NULL != pnIpAddrs) { *pnIpAddrs = pqsResult->dwNumberOfCsAddrs; }
  291. rgiaLocalIpAddrs = NULL;
  292. rgiaRemoteIpAddrs = NULL;
  293. hr = S_OK;
  294. error:
  295. if (NULL != pbRetry) {
  296. // Probably shouldn't be removing manual peers. Always retry.
  297. *pbRetry = true;
  298. }
  299. if (NULL != rgiaLocalIpAddrs) {
  300. LocalFree(rgiaLocalIpAddrs);
  301. }
  302. if (NULL != rgiaRemoteIpAddrs) {
  303. LocalFree(rgiaRemoteIpAddrs);
  304. }
  305. if (NULL != pqsResult) {
  306. LocalFree(pqsResult);
  307. }
  308. if (INVALID_HANDLE_VALUE != hSearch) {
  309. if (SOCKET_ERROR == WSALookupServiceEnd(hSearch)) {
  310. HRESULT hr2 = HRESULT_FROM_WIN32(WSAGetLastError());
  311. _IgnoreError(hr2, "WSALookupServiceEnd");
  312. }
  313. }
  314. return hr;
  315. }
  316. //--------------------------------------------------------------------
  317. // initialize the socket layer
  318. HRESULT OpenSocketLayer(void) {
  319. HRESULT hr;
  320. int nRetVal;
  321. WSADATA wdWinsockInfo;
  322. nRetVal=WSAStartup(0x0002/*version*/, &wdWinsockInfo);
  323. if (0!=nRetVal) {
  324. hr=HRESULT_FROM_WIN32(nRetVal);
  325. _JumpError(hr, error, "WSAStartup");
  326. }
  327. //DebugWPrintf4(L"Socket layer initialized. v:0x%04X hv:0x%04X desc:\"%S\" status:\"%S\"\n",
  328. // wdWinsockInfo.wVersion, wdWinsockInfo.wHighVersion, wdWinsockInfo.szDescription,
  329. // wdWinsockInfo.szSystemStatus);
  330. hr=S_OK;
  331. error:
  332. return hr;
  333. }
  334. //--------------------------------------------------------------------
  335. // close down the socket layer
  336. HRESULT CloseSocketLayer(void) {
  337. HRESULT hr;
  338. int nRetVal;
  339. nRetVal=WSACleanup();
  340. if (SOCKET_ERROR==nRetVal) {
  341. _JumpLastError(hr, error, "WSACleanup");
  342. }
  343. //DebugWPrintf0(L"Socket layer cleanup successful\n");
  344. hr=S_OK;
  345. error:
  346. return hr;
  347. }
  348. //--------------------------------------------------------------------
  349. HRESULT GetSystemErrorString(HRESULT hrIn, WCHAR ** pwszError) {
  350. HRESULT hr=S_OK;
  351. DWORD dwResult;
  352. WCHAR * rgParams[2]={
  353. NULL,
  354. (WCHAR *)(ULONG_PTR)hrIn
  355. };
  356. // must be cleaned up
  357. WCHAR * wszErrorMessage=NULL;
  358. WCHAR * wszFullErrorMessage=NULL;
  359. // initialize input params
  360. *pwszError=NULL;
  361. // get the message from the system
  362. dwResult=FormatMessage(
  363. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  364. NULL/*ignored*/, hrIn, 0/*language*/, (WCHAR *)&wszErrorMessage, 0/*min-size*/, NULL/*valist*/);
  365. if (0==dwResult) {
  366. if (ERROR_MR_MID_NOT_FOUND==GetLastError()) {
  367. rgParams[0]=L"";
  368. } else {
  369. _JumpLastError(hr, error, "FormatMessage");
  370. }
  371. } else {
  372. rgParams[0]=wszErrorMessage;
  373. // trim off \r\n if it exists
  374. if (L'\r'==wszErrorMessage[wcslen(wszErrorMessage)-2]) {
  375. wszErrorMessage[wcslen(wszErrorMessage)-2]=L'\0';
  376. }
  377. }
  378. // add the error number
  379. dwResult=FormatMessage(
  380. FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
  381. L"%1 (0x%2!08X!)", 0, 0/*language*/, (WCHAR *)&wszFullErrorMessage, 0/*min-size*/, (va_list *)rgParams);
  382. if (0==dwResult) {
  383. _JumpLastError(hr, error, "FormatMessage");
  384. }
  385. // success
  386. *pwszError=wszFullErrorMessage;
  387. wszFullErrorMessage=NULL;
  388. hr=S_OK;
  389. error:
  390. if (NULL!=wszErrorMessage) {
  391. LocalFree(wszErrorMessage);
  392. }
  393. if (NULL!=wszFullErrorMessage) {
  394. LocalFree(wszFullErrorMessage);
  395. }
  396. return hr;
  397. }
  398. //--------------------------------------------------------------------
  399. extern "C" void MIDL_user_free(void * pvValue) {
  400. LocalFree(pvValue);
  401. }
  402. //--------------------------------------------------------------------
  403. extern "C" void * MIDL_user_allocate(size_t n) {
  404. return (LocalAlloc(LPTR, n));
  405. }