Leaked source code of windows server 2003
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.

1275 lines
28 KiB

  1. /******************************************************************
  2. CPingProvider.CPP -- WMI provider class implementation
  3. Copyright (c) 2000-2001 Microsoft Corporation, All Rights Reserved
  4. Description:
  5. ******************************************************************/
  6. #include <stdafx.h>
  7. #include <ntddtcp.h>
  8. #include <ipinfo.h>
  9. #include <tdiinfo.h>
  10. #include <winsock2.h>
  11. #include <provimex.h>
  12. #include <provexpt.h>
  13. #include <provtempl.h>
  14. #include <provmt.h>
  15. #include <typeinfo.h>
  16. #include <provcont.h>
  17. #include <provevt.h>
  18. #include <provthrd.h>
  19. #include <provlog.h>
  20. #include <provval.h>
  21. #include <provtype.h>
  22. #include <provtree.h>
  23. #include <provdnf.h>
  24. #include <winsock.h>
  25. #include "ipexport.h"
  26. #include "icmpapi.h"
  27. #include ".\res_str.h"
  28. #include <Allocator.h>
  29. #include <Thread.h>
  30. #include <HashTable.h>
  31. #include <PingProv.h>
  32. #include <Pingtask.h>
  33. #include <Pingfac.h>
  34. extern HMODULE ghModule ;
  35. // Property names
  36. //===============
  37. const WCHAR *Ping_Address = L"Address" ;
  38. const WCHAR *Ping_Timeout = L"Timeout" ;
  39. const WCHAR *Ping_TimeToLive = L"TimeToLive" ;
  40. const WCHAR *Ping_BufferSize = L"BufferSize" ;
  41. const WCHAR *Ping_NoFragmentation = L"NoFragmentation" ;
  42. const WCHAR *Ping_TypeofService = L"TypeofService" ;
  43. const WCHAR *Ping_RecordRoute = L"RecordRoute" ;
  44. const WCHAR *Ping_TimestampRoute = L"TimestampRoute" ;
  45. const WCHAR *Ping_SourceRouteType = L"SourceRouteType" ;
  46. const WCHAR *Ping_SourceRoute = L"SourceRoute" ;
  47. const WCHAR *Ping_ResolveAddressNames = L"ResolveAddressNames" ;
  48. const static WCHAR *Ping_StatusCode = L"StatusCode" ;
  49. const static WCHAR *Ping_ResponseTime = L"ResponseTime" ;
  50. const static WCHAR *Ping_RouteRecord = L"RouteRecord" ;
  51. const static WCHAR *Ping_ReplySize = L"ReplySize" ;
  52. const static WCHAR *Ping_ReplyInconsistency = L"ReplyInconsistency" ;
  53. const static WCHAR *Ping_ResponseTimeToLive = L"ResponseTimeToLive" ;
  54. const static WCHAR *Ping_ProtocolAddress = L"ProtocolAddress" ;
  55. const static WCHAR *Ping_TimeStampRecord = L"TimeStampRecord" ;
  56. const static WCHAR *Ping_TimeStampRecordAddress = L"TimeStampRecordAddress" ;
  57. const static WCHAR *Ping_TimeStampRecordAddressResolved = L"TimeStampRecordAddressResolved" ;
  58. const static WCHAR *Ping_RouteRecordResolved = L"RouteRecordResolved" ;
  59. const static WCHAR *Ping_ProtocolAddressResolved = L"ProtocolAddressResolved" ;
  60. const static WCHAR *Ping_ResolveError = L"PrimaryAddressResolutionStatus" ;
  61. CPingTaskObject::CPingErrorObject::~CPingErrorObject()
  62. {
  63. if (m_Description != NULL)
  64. {
  65. delete [] m_Description;
  66. }
  67. }
  68. void CPingTaskObject::CPingErrorObject::SetInfo(LPCWSTR a_description, HRESULT a_status)
  69. {
  70. m_Status = a_status;
  71. if (m_Description != NULL)
  72. {
  73. delete [] m_Description;
  74. m_Description = NULL;
  75. }
  76. if (a_description != NULL)
  77. {
  78. int t_len = wcslen(a_description);
  79. if (t_len > 0)
  80. {
  81. m_Description = new WCHAR[t_len+1];
  82. m_Description[t_len] = L'\0';
  83. wcsncpy(m_Description, a_description, t_len);
  84. }
  85. }
  86. }
  87. CPingTaskObject::CPingTaskObject (CPingProvider *a_Provider ,
  88. IWbemObjectSink *a_NotificationHandler ,
  89. IWbemContext *a_Ctx
  90. ): m_NotificationHandler(NULL),
  91. m_Ctx(NULL),
  92. m_Provider(NULL),
  93. m_PingCount(0),
  94. m_ThreadToken(NULL)
  95. {
  96. InitializeCriticalSection(&m_CS);
  97. if (a_NotificationHandler != NULL)
  98. {
  99. m_NotificationHandler = a_NotificationHandler;
  100. m_NotificationHandler->AddRef();
  101. }
  102. if (a_Ctx != NULL)
  103. {
  104. m_Ctx = a_Ctx;
  105. m_Ctx->AddRef();
  106. }
  107. if (a_Provider != NULL)
  108. {
  109. m_Provider = a_Provider;
  110. m_Provider->AddRef();
  111. }
  112. }
  113. CPingTaskObject::~CPingTaskObject ()
  114. {
  115. if (m_NotificationHandler != NULL)
  116. {
  117. IWbemClassObject *t_NotifyStatus = NULL ;
  118. BOOL t_Status = TRUE;
  119. if ( FAILED(m_ErrorObject.GetStatus ()) )
  120. {
  121. t_Status = GetStatusObject ( &t_NotifyStatus ) ;
  122. }
  123. if ( t_Status )
  124. {
  125. m_NotificationHandler->SetStatus ( 0 , m_ErrorObject.GetStatus () , 0 , t_NotifyStatus ) ;
  126. if (t_NotifyStatus)
  127. {
  128. t_NotifyStatus->Release () ;
  129. }
  130. }
  131. else
  132. {
  133. m_NotificationHandler->SetStatus ( 0 , m_ErrorObject.GetStatus () , 0 , NULL ) ;
  134. }
  135. m_NotificationHandler->Release();
  136. m_NotificationHandler = NULL;
  137. }
  138. if (m_Ctx != NULL)
  139. {
  140. m_Ctx->Release();
  141. m_Ctx = NULL;
  142. }
  143. if (m_Provider != NULL)
  144. {
  145. m_Provider->Release();
  146. m_Provider = NULL;
  147. }
  148. if (m_ThreadToken != NULL)
  149. {
  150. CloseHandle(m_ThreadToken);
  151. m_ThreadToken = NULL;
  152. }
  153. DeleteCriticalSection(&m_CS);
  154. }
  155. void CPingTaskObject::DecrementPingCount()
  156. {
  157. if (0 == InterlockedDecrement(&m_PingCount))
  158. {
  159. delete this;
  160. }
  161. }
  162. BOOL CPingTaskObject :: GetThreadToken()
  163. {
  164. BOOL t_RetVal = OpenThreadToken(
  165. GetCurrentThread(), // handle to thread
  166. TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE, // access to process
  167. TRUE, // use thread security
  168. &m_ThreadToken // pointer to token handle
  169. );
  170. if (!t_RetVal)
  171. {
  172. SetErrorInfo(IDS_DUP_THRDTOKEN ,
  173. WBEM_E_ACCESS_DENIED ) ;
  174. }
  175. return t_RetVal;
  176. }
  177. BOOL CPingTaskObject :: SetThreadToken(BOOL a_Reset)
  178. {
  179. BOOL t_RetVal = ::SetThreadToken(NULL, a_Reset ? NULL : m_ThreadToken);
  180. return t_RetVal;
  181. }
  182. BOOL CPingTaskObject :: GetStatusObject ( IWbemClassObject **a_NotifyObject )
  183. {
  184. HRESULT t_Result = WBEM_E_FAILED ;
  185. if ( m_Provider->GetNotificationObject ( m_Ctx, a_NotifyObject ) )
  186. {
  187. _variant_t t_Variant((long) m_ErrorObject.GetStatus (), VT_I4) ;
  188. t_Result = (*a_NotifyObject)->Put ( WBEM_PROPERTY_STATUSCODE , 0 , & t_Variant , 0 ) ;
  189. if ( SUCCEEDED ( t_Result ) )
  190. {
  191. LPCWSTR t_descr = m_ErrorObject.GetDescription ();
  192. if ( t_descr != NULL )
  193. {
  194. t_Variant = t_descr ;
  195. t_Result = (*a_NotifyObject)->Put ( WBEM_PROPERTY_PROVSTATUSMESSAGE , 0 , & t_Variant , 0 ) ;
  196. if ( ! SUCCEEDED ( t_Result ) )
  197. {
  198. (*a_NotifyObject)->Release () ;
  199. *a_NotifyObject = NULL;
  200. }
  201. }
  202. }
  203. else
  204. {
  205. (*a_NotifyObject)->Release () ;
  206. *a_NotifyObject = NULL ;
  207. }
  208. }
  209. return (SUCCEEDED (t_Result)) ;
  210. }
  211. BOOL CPingTaskObject::GetClassObject ( IWbemClassObject **a_ppClass )
  212. {
  213. BOOL t_bRetVal = FALSE;
  214. if ((a_ppClass != NULL) && (m_Provider != NULL))
  215. {
  216. *a_ppClass = NULL;
  217. if (m_Provider->GetClassObject(a_ppClass) && ((*a_ppClass) != NULL))
  218. {
  219. t_bRetVal = TRUE;
  220. }
  221. }
  222. return t_bRetVal;
  223. }
  224. HRESULT CPingTaskObject::Icmp_ResolveAddress ( LPCWSTR a_Path , ULONG &a_IpAddress, DWORD *a_pdwErr )
  225. {
  226. HRESULT t_Result = WBEM_E_NOT_FOUND ;
  227. if (a_pdwErr)
  228. {
  229. *a_pdwErr = 0 ;
  230. }
  231. ProvIpAddressType t_IpAddress ( a_Path ) ;
  232. if ( ! t_IpAddress.IsValid () )
  233. {
  234. char *t_AnsiAddress = UnicodeToDbcsString ( a_Path ) ;
  235. if ( t_AnsiAddress )
  236. {
  237. struct hostent *t_HostEntry = gethostbyname ( t_AnsiAddress ) ;
  238. if ( t_HostEntry )
  239. {
  240. /*
  241. * If we find a host entry, set up the internet address
  242. */
  243. t_IpAddress = ProvIpAddressType ( ntohl ( * ( long * ) t_HostEntry->h_addr ) ) ;
  244. }
  245. else
  246. {
  247. DWORD dwErr = WSAGetLastError();
  248. if (a_pdwErr)
  249. {
  250. *a_pdwErr = dwErr ;
  251. }
  252. }
  253. delete [] t_AnsiAddress ;
  254. }
  255. }
  256. if ( t_IpAddress.IsValid () )
  257. {
  258. a_IpAddress = htonl ( t_IpAddress.GetValue () ) ;
  259. t_Result = S_OK ;
  260. }
  261. return t_Result ;
  262. }
  263. HRESULT CPingTaskObject::SetInstanceKeys(IWbemClassObject *a_Inst , CPingCallBackObject *a_Reply)
  264. {
  265. if ((a_Inst == NULL) || (a_Reply == NULL))
  266. {
  267. return WBEM_E_FAILED;
  268. }
  269. //set all 11 keys!
  270. HRESULT t_RetVal = SetUint32Property( a_Inst, Ping_Timeout, a_Reply->GetTimeout() ) ;
  271. if (SUCCEEDED (t_RetVal))
  272. {
  273. t_RetVal = SetUint32Property( a_Inst, Ping_TimeToLive, a_Reply->GetTimeToLive() ) ;
  274. }
  275. if (SUCCEEDED (t_RetVal))
  276. {
  277. t_RetVal = SetUint32Property( a_Inst, Ping_BufferSize, a_Reply->GetSendSize() ) ;
  278. }
  279. if (SUCCEEDED (t_RetVal))
  280. {
  281. t_RetVal = SetUint32Property( a_Inst, Ping_TypeofService, a_Reply->GetTypeofService() ) ;
  282. }
  283. if (SUCCEEDED (t_RetVal))
  284. {
  285. t_RetVal = SetUint32Property( a_Inst, Ping_RecordRoute, a_Reply->GetRecordRoute() ) ;
  286. }
  287. if (SUCCEEDED (t_RetVal))
  288. {
  289. t_RetVal = SetUint32Property( a_Inst, Ping_TimestampRoute, a_Reply->GetTimestampRoute() ) ;
  290. }
  291. if (SUCCEEDED (t_RetVal))
  292. {
  293. t_RetVal = SetUint32Property( a_Inst, Ping_SourceRouteType, a_Reply->GetSourceRouteType() ) ;
  294. }
  295. if (SUCCEEDED (t_RetVal))
  296. {
  297. t_RetVal = SetBOOLProperty( a_Inst, Ping_NoFragmentation, a_Reply->GetNoFragmentation() ) ;
  298. }
  299. if (SUCCEEDED (t_RetVal))
  300. {
  301. t_RetVal = SetBOOLProperty( a_Inst, Ping_ResolveAddressNames, a_Reply->GetResolveAddress() ) ;
  302. }
  303. if (SUCCEEDED (t_RetVal))
  304. {
  305. t_RetVal = SetStringProperty( a_Inst, Ping_SourceRoute, a_Reply->GetSourceRoute() ) ;
  306. }
  307. if (SUCCEEDED (t_RetVal))
  308. {
  309. t_RetVal = SetStringProperty( a_Inst, Ping_Address, a_Reply->GetAddressString()) ;
  310. }
  311. if (SUCCEEDED (t_RetVal))
  312. {
  313. //not a key so we don't report if this fails...
  314. SetUint32Property( a_Inst, Ping_ResolveError, a_Reply->GetResolveError() ) ;
  315. }
  316. return t_RetVal;
  317. }
  318. HRESULT CPingTaskObject::SetUint32Property(
  319. IWbemClassObject *a_Inst,
  320. LPCWSTR a_Name,
  321. ULONG a_Val
  322. )
  323. {
  324. if ((a_Inst == NULL) || (a_Name == NULL))
  325. {
  326. return WBEM_E_FAILED;
  327. }
  328. _variant_t t_var((long)a_Val);
  329. return (a_Inst->Put(a_Name, 0, &t_var, 0));
  330. }
  331. HRESULT CPingTaskObject::SetUint32ArrayProperty(
  332. IWbemClassObject *a_Inst ,
  333. LPCWSTR a_Name ,
  334. ULONG* a_Vals ,
  335. ULONG a_Count
  336. )
  337. {
  338. if ((a_Inst == NULL) || (a_Name == NULL))
  339. {
  340. return WBEM_E_FAILED;
  341. }
  342. SAFEARRAYBOUND t_rgsabound[1];
  343. SAFEARRAY* t_psa = NULL;
  344. t_rgsabound[0].lLbound = 0;
  345. t_rgsabound[0].cElements = a_Count;
  346. t_psa = SafeArrayCreate(VT_I4, 1, t_rgsabound);
  347. HRESULT t_RetVal = S_OK;
  348. if (NULL != t_psa)
  349. {
  350. try
  351. {
  352. LONG *t_pdata = NULL;
  353. if (SUCCEEDED(SafeArrayAccessData(t_psa, (void **)&t_pdata)))
  354. {
  355. try
  356. {
  357. memcpy((void *)t_pdata, (void *)a_Vals, a_Count*sizeof(ULONG));
  358. SafeArrayUnaccessData(t_psa);
  359. }
  360. catch (...)
  361. {
  362. SafeArrayUnaccessData(t_psa);
  363. throw;
  364. }
  365. VARIANT t_var;
  366. VariantInit(&t_var);
  367. t_var.vt = VT_ARRAY|VT_I4;
  368. t_var.parray = t_psa;
  369. t_psa = NULL;
  370. try
  371. {
  372. t_RetVal = a_Inst->Put(a_Name, 0, &t_var, 0);
  373. }
  374. catch (...)
  375. {
  376. VariantClear(&t_var);
  377. throw;
  378. }
  379. VariantClear(&t_var);
  380. }
  381. }
  382. catch(...)
  383. {
  384. if (t_psa != NULL)
  385. {
  386. SafeArrayDestroy(t_psa);
  387. }
  388. throw;
  389. }
  390. }
  391. else
  392. {
  393. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  394. }
  395. return t_RetVal;
  396. }
  397. HRESULT CPingTaskObject::SetStringProperty(
  398. IWbemClassObject *a_Inst,
  399. LPCWSTR a_Name,
  400. LPCWSTR a_Val
  401. )
  402. {
  403. if ((a_Inst == NULL) || (a_Name == NULL))
  404. {
  405. return WBEM_E_FAILED;
  406. }
  407. _variant_t t_var(a_Val);
  408. return (a_Inst->Put(a_Name, 0, &t_var, 0));
  409. }
  410. HRESULT CPingTaskObject::SetBOOLProperty(
  411. IWbemClassObject *a_Inst,
  412. LPCWSTR a_Name,
  413. BOOL a_Val
  414. )
  415. {
  416. if ((a_Inst == NULL) || (a_Name == NULL))
  417. {
  418. return WBEM_E_FAILED;
  419. }
  420. _variant_t t_var(a_Val ? true : false);
  421. return (a_Inst->Put(a_Name, 0, &t_var, 0));
  422. }
  423. void CPingTaskObject::IPAddressToString(_variant_t &a_var, ULONG a_Val, BOOL a_Resolve)
  424. {
  425. if (!a_Resolve)
  426. {
  427. ProvIpAddressType t_ProtocolAddress ( ntohl(a_Val) ) ;
  428. wchar_t *t_AddressString = t_ProtocolAddress.GetStringValue () ;
  429. a_var = t_AddressString;
  430. delete [] t_AddressString ;
  431. }
  432. else
  433. {
  434. struct in_addr t_Address;
  435. t_Address.S_un.S_addr = a_Val; //assumes in param in network order when resolving
  436. struct hostent *t_hostent = gethostbyaddr((char *) &t_Address, sizeof(t_Address), AF_INET);
  437. if (t_hostent != NULL)
  438. {
  439. a_var = t_hostent->h_name;
  440. }
  441. else
  442. {
  443. ProvIpAddressType t_ProtocolAddress ( ntohl(a_Val) ) ;
  444. wchar_t *t_AddressString = t_ProtocolAddress.GetStringValue () ;
  445. a_var = t_AddressString;
  446. delete [] t_AddressString ;
  447. }
  448. }
  449. }
  450. HRESULT CPingTaskObject::SetIPProperty(
  451. IWbemClassObject *a_Inst ,
  452. LPCWSTR a_Name ,
  453. ULONG a_Val ,
  454. BOOL a_Resolve
  455. )
  456. {
  457. if ((a_Inst == NULL) || (a_Name == NULL))
  458. {
  459. return WBEM_E_FAILED;
  460. }
  461. _variant_t t_var;
  462. IPAddressToString(t_var, a_Val, a_Resolve);
  463. return (a_Inst->Put(a_Name, 0, &t_var, 0));
  464. }
  465. HRESULT CPingTaskObject::SetIPArrayProperty(
  466. IWbemClassObject *a_Inst ,
  467. LPCWSTR a_Name ,
  468. ULONG* a_Vals ,
  469. ULONG a_Count ,
  470. BOOL a_Resolve
  471. )
  472. {
  473. if ((a_Inst == NULL) || (a_Name == NULL))
  474. {
  475. return WBEM_E_FAILED;
  476. }
  477. SAFEARRAYBOUND t_rgsabound[1];
  478. SAFEARRAY* t_psa = NULL;
  479. t_rgsabound[0].lLbound = 0;
  480. t_rgsabound[0].cElements = a_Count;
  481. t_psa = SafeArrayCreate(VT_BSTR, 1, t_rgsabound);
  482. HRESULT t_RetVal = S_OK;
  483. if (NULL != t_psa)
  484. {
  485. try
  486. {
  487. BSTR *t_pdata = NULL;
  488. if (SUCCEEDED(SafeArrayAccessData(t_psa, (void **)&t_pdata)))
  489. {
  490. try
  491. {
  492. for (int i = 0; i < a_Count; i++)
  493. {
  494. _variant_t t_var;
  495. IPAddressToString(t_var, a_Vals[i], a_Resolve);
  496. VARIANT t_NoDelVar = t_var.Detach() ;
  497. t_pdata[i] = t_NoDelVar.bstrVal;
  498. }
  499. SafeArrayUnaccessData(t_psa);
  500. }
  501. catch (...)
  502. {
  503. SafeArrayUnaccessData(t_psa);
  504. throw;
  505. }
  506. VARIANT t_var;
  507. VariantInit(&t_var);
  508. t_var.vt = VT_ARRAY|VT_BSTR;
  509. t_var.parray = t_psa;
  510. t_psa = NULL;
  511. try
  512. {
  513. t_RetVal = a_Inst->Put(a_Name, 0, &t_var, 0);
  514. }
  515. catch (...)
  516. {
  517. VariantClear(&t_var);
  518. throw;
  519. }
  520. VariantClear(&t_var);
  521. }
  522. }
  523. catch(...)
  524. {
  525. if (t_psa != NULL)
  526. {
  527. SafeArrayDestroy(t_psa);
  528. }
  529. throw;
  530. }
  531. }
  532. else
  533. {
  534. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  535. }
  536. return t_RetVal;
  537. }
  538. HRESULT CPingTaskObject::Icmp_IndicateResolveError (CPingCallBackObject *a_Reply)
  539. {
  540. HRESULT t_RetVal = S_OK;
  541. IWbemClassObjectPtr t_Cls;
  542. IWbemClassObjectPtr t_Inst;
  543. if (a_Reply != NULL)
  544. {
  545. if (GetClassObject ( &t_Cls ) )
  546. {
  547. t_RetVal = t_Cls->SpawnInstance(0, &t_Inst);
  548. if (SUCCEEDED (t_RetVal))
  549. {
  550. //put the keys...
  551. t_RetVal = SetInstanceKeys(t_Inst , a_Reply);
  552. if (SUCCEEDED(t_RetVal))
  553. {
  554. //Indicate!
  555. IWbemClassObject *t_pTmp = (IWbemClassObject*) t_Inst;
  556. m_NotificationHandler->Indicate(1, &t_pTmp);
  557. }
  558. }
  559. }
  560. }
  561. else
  562. {
  563. //should not be NULL!!
  564. t_RetVal = WBEM_E_FAILED;
  565. }
  566. return t_RetVal;
  567. }
  568. HRESULT CPingTaskObject::Icmp_DecodeAndIndicate (CPingCallBackObject *a_Reply)
  569. {
  570. HRESULT t_RetVal = S_OK;
  571. PICMP_ECHO_REPLY t_Reply = ( PICMP_ECHO_REPLY ) a_Reply->GetReplyBuffer() ;
  572. IWbemClassObjectPtr t_Cls;
  573. IWbemClassObjectPtr t_Inst;
  574. if (t_Reply != NULL)
  575. {
  576. if (GetClassObject ( &t_Cls ) )
  577. {
  578. t_RetVal = t_Cls->SpawnInstance(0, &t_Inst);
  579. if (SUCCEEDED (t_RetVal))
  580. {
  581. //put the keys...
  582. t_RetVal = SetInstanceKeys(t_Inst , a_Reply);
  583. }
  584. if (SUCCEEDED (t_RetVal))
  585. {
  586. ULONG t_StatusCode = 0;
  587. if ( ( 0 != IcmpParseReplies(t_Reply, a_Reply->GetSendSize()) ) &&
  588. ( t_Reply->Status == IP_SUCCESS ) )
  589. {
  590. ProvIpAddressType t_IpAddress((ULONG)ntohl(t_Reply->Address ));
  591. SetIPProperty(t_Inst , Ping_ProtocolAddress, t_Reply->Address , FALSE);
  592. if (a_Reply->GetResolveAddress())
  593. {
  594. SetIPProperty(t_Inst , Ping_ProtocolAddressResolved, t_Reply->Address , TRUE);
  595. }
  596. SetUint32Property( t_Inst, Ping_ResponseTime, t_Reply->RoundTripTime ) ;
  597. SetUint32Property( t_Inst, Ping_ResponseTimeToLive, t_Reply->Options.Ttl ) ;
  598. SetUint32Property( t_Inst, Ping_ReplySize, t_Reply->DataSize ) ;
  599. BOOL t_ReplyInconsistency = FALSE;
  600. if ( t_Reply->DataSize == a_Reply->GetSendSize() )
  601. {
  602. try
  603. {
  604. UCHAR *t_SendPtr = & ( a_Reply->GetSendBuffer() [ 0 ] );
  605. UCHAR *t_ReplyPtr = (UCHAR*) t_Reply->Data ;
  606. for (ULONG t_Index = 0; t_Index < t_Reply->DataSize; t_Index ++ )
  607. {
  608. if ( *t_SendPtr ++ != *t_ReplyPtr ++ )
  609. {
  610. t_ReplyInconsistency = TRUE ;
  611. break;
  612. }
  613. }
  614. }
  615. catch(...)
  616. {
  617. t_ReplyInconsistency = TRUE ;
  618. }
  619. }
  620. else
  621. {
  622. t_ReplyInconsistency = TRUE ;
  623. }
  624. SetBOOLProperty( t_Inst, Ping_ReplyInconsistency, t_ReplyInconsistency ) ;
  625. if ( t_Reply->Options.OptionsSize )
  626. {
  627. ULONG t_RouteSourceCount = 0;
  628. ULONG *t_RouteSource = NULL;
  629. ULONG t_TimestampCount = 0;
  630. ULONG *t_Timestamp = NULL;
  631. ULONG *t_TimestampRoute = NULL;
  632. HRESULT t_Result = Icmp_DecodeResponse (
  633. t_Reply ,
  634. t_RouteSourceCount ,
  635. t_RouteSource ,
  636. t_TimestampCount ,
  637. t_TimestampRoute ,
  638. t_Timestamp
  639. ) ;
  640. if (SUCCEEDED (t_Result))
  641. {
  642. if (t_RouteSource != NULL)
  643. {
  644. SetIPArrayProperty(
  645. t_Inst ,
  646. Ping_RouteRecord ,
  647. t_RouteSource ,
  648. t_RouteSourceCount ,
  649. FALSE
  650. );
  651. }
  652. if (t_TimestampRoute != NULL)
  653. {
  654. SetIPArrayProperty(
  655. t_Inst ,
  656. Ping_TimeStampRecordAddress ,
  657. t_TimestampRoute ,
  658. t_TimestampCount ,
  659. FALSE
  660. );
  661. }
  662. if (t_Timestamp != NULL)
  663. {
  664. SetUint32ArrayProperty(
  665. t_Inst ,
  666. Ping_TimeStampRecord ,
  667. t_Timestamp ,
  668. t_TimestampCount
  669. );
  670. }
  671. if (a_Reply->GetResolveAddress())
  672. {
  673. if (t_RouteSource != NULL)
  674. {
  675. SetIPArrayProperty(
  676. t_Inst ,
  677. Ping_RouteRecordResolved ,
  678. t_RouteSource ,
  679. t_RouteSourceCount ,
  680. TRUE
  681. );
  682. }
  683. if (t_TimestampRoute != NULL)
  684. {
  685. SetIPArrayProperty(
  686. t_Inst ,
  687. Ping_TimeStampRecordAddressResolved ,
  688. t_TimestampRoute ,
  689. t_TimestampCount ,
  690. TRUE
  691. );
  692. }
  693. }
  694. delete [] t_RouteSource;
  695. delete [] t_TimestampRoute;
  696. delete [] t_Timestamp;
  697. }
  698. }
  699. }
  700. else
  701. {
  702. t_StatusCode = t_Reply->Status ;
  703. }
  704. SetUint32Property( t_Inst, Ping_StatusCode, t_StatusCode ) ;
  705. }
  706. if (SUCCEEDED(t_RetVal))
  707. {
  708. //Indicate!
  709. IWbemClassObject *t_pTmp = (IWbemClassObject*) t_Inst;
  710. m_NotificationHandler->Indicate(1, &t_pTmp);
  711. }
  712. }
  713. else
  714. {
  715. t_RetVal = WBEM_E_FAILED;
  716. }
  717. }
  718. else
  719. {
  720. //should not be NULL!!
  721. t_RetVal = WBEM_E_FAILED;
  722. }
  723. return t_RetVal;
  724. }
  725. void CPingTaskObject::SetErrorInfo(DWORD a_ErrMsgID, HRESULT a_HRes, BOOL a_Force)
  726. {
  727. CCritSecAutoUnlock t_AutoLockUnlock(&m_CS);
  728. if (a_Force || SUCCEEDED(m_ErrorObject.GetStatus()) )
  729. {
  730. //convert id to string...
  731. WCHAR t_ErrMsgBuff[255];
  732. WCHAR *t_ErrMsg = t_ErrMsgBuff;
  733. int t_buffSz = 255;
  734. int t_copied = LoadString(ghModule, a_ErrMsgID, t_ErrMsg, t_buffSz);
  735. //try expanding a couple of times
  736. //if it is still too big, too bad it'll be truncated
  737. //not even localized strings should be this big (1500chars = 3k)
  738. for (int i = 2; (i < 4) && (t_copied == t_buffSz); i++)
  739. {
  740. t_ErrMsg = new WCHAR[t_buffSz * i];
  741. t_buffSz = t_buffSz * i;
  742. t_copied = LoadString(ghModule, a_ErrMsgID, t_ErrMsg, t_buffSz);
  743. }
  744. m_ErrorObject.SetInfo(t_ErrMsg, a_HRes);
  745. if (t_ErrMsg != t_ErrMsgBuff)
  746. {
  747. delete [] t_ErrMsg;
  748. }
  749. }
  750. }
  751. HRESULT CPingTaskObject::Icmp_DecodeResponse (PICMP_ECHO_REPLY a_Reply ,
  752. ULONG &a_RouteSourceCount ,
  753. ULONG *&a_RouteSource ,
  754. ULONG &a_TimestampCount ,
  755. ULONG *&a_TimestampRoute ,
  756. ULONG *&a_Timestamp)
  757. {
  758. HRESULT t_Result = S_OK ;
  759. uchar *t_OptionPtr = a_Reply->Options.OptionsData ;
  760. uchar *t_EndPtr = t_OptionPtr + a_Reply->Options.OptionsSize ;
  761. BOOL t_Done = FALSE ;
  762. try
  763. {
  764. while ( ( t_OptionPtr < t_EndPtr ) && ! t_Done )
  765. {
  766. // Get the option type
  767. switch ( t_OptionPtr [ 0 ] )
  768. {
  769. case IP_OPT_EOL:
  770. {
  771. t_Done = TRUE;
  772. }
  773. break;
  774. case IP_OPT_NOP:
  775. {
  776. t_OptionPtr ++ ;
  777. }
  778. break ;
  779. case IP_OPT_SECURITY:
  780. {
  781. t_OptionPtr += 11 ;
  782. }
  783. break ;
  784. case IP_OPT_SID:
  785. {
  786. t_OptionPtr += 4;
  787. }
  788. break;
  789. case IP_OPT_RR:
  790. case IP_OPT_LSRR:
  791. case IP_OPT_SSRR:
  792. {
  793. if ( ( t_OptionPtr + 3 ) <= t_EndPtr )
  794. {
  795. ULONG t_OptionLength = t_OptionPtr [ 1 ] ;
  796. if ( ( ( t_OptionPtr + t_OptionLength ) > t_EndPtr ) || ( t_OptionLength < 3 ) )
  797. {
  798. // INVALID_RR_OPTION
  799. t_Done = TRUE ;
  800. t_Result = WBEM_E_FAILED ;
  801. }
  802. else
  803. {
  804. ULONG t_RouteTableEndOffset = t_OptionPtr [ 2 ] ;
  805. if ( t_RouteTableEndOffset < 4 )
  806. {
  807. // Advance because the entry is a bad encoding, require 4 bytes for atleast one address
  808. t_OptionPtr += t_OptionLength ;
  809. }
  810. else
  811. {
  812. if ( t_RouteTableEndOffset > ( t_OptionLength + 1 ) )
  813. {
  814. // The actual route table end index is larger than the option itself, therefore decode as much as possible
  815. t_RouteTableEndOffset = t_OptionLength + 1 ;
  816. }
  817. // Count the entries
  818. ULONG t_RouteEntryOffset = 4 ;
  819. a_RouteSourceCount = 0;
  820. while ( ( t_RouteEntryOffset + 3 ) < t_RouteTableEndOffset )
  821. {
  822. a_RouteSourceCount ++ ;
  823. t_RouteEntryOffset += 4 ;
  824. }
  825. // Extract the routes
  826. if (a_RouteSourceCount > 0)
  827. {
  828. a_RouteSource = new ULONG[a_RouteSourceCount];
  829. a_RouteSourceCount = 0;
  830. t_RouteEntryOffset = 4 ;
  831. while ( ( t_RouteEntryOffset + 3 ) < t_RouteTableEndOffset )
  832. {
  833. // a_RouteSource[a_RouteSourceCount++] = * ( ( IPAddr * ) ( t_OptionPtr + t_RouteEntryOffset - 1 ) ) ;
  834. memcpy ( &a_RouteSource[a_RouteSourceCount++], t_OptionPtr + t_RouteEntryOffset - 1, sizeof ( IPAddr ) );
  835. t_RouteEntryOffset += 4 ;
  836. }
  837. }
  838. // Advance to the next option
  839. t_OptionPtr += t_OptionLength ;
  840. }
  841. }
  842. }
  843. else
  844. {
  845. // INVALID_RR_OPTION
  846. t_Done = TRUE ;
  847. t_Result = WBEM_E_FAILED ;
  848. }
  849. }
  850. break;
  851. case IP_OPT_TS:
  852. {
  853. if ( ( t_OptionPtr + 4 ) <= t_EndPtr )
  854. {
  855. ULONG t_OptionLength = t_OptionPtr [ 1 ] ;
  856. ULONG t_TimestampTableEndOffset = t_OptionPtr [ 2 ] ;
  857. if ( t_TimestampTableEndOffset >= 5 )
  858. {
  859. if ( t_TimestampTableEndOffset > ( t_OptionLength + 1 ) )
  860. {
  861. // The actual timestamp table end index is larger than the option itself, therefore decode as much as possible
  862. t_TimestampTableEndOffset = t_OptionLength + 1 ;
  863. }
  864. ULONG t_AddressMode = t_OptionPtr [ 3 ] & 1 ;
  865. // Count the entries
  866. ULONG t_TimestampEntryOffset = 5 ;
  867. while ( ( t_TimestampEntryOffset + 3 ) < t_TimestampTableEndOffset )
  868. {
  869. if ( t_AddressMode )
  870. {
  871. if ( ( t_TimestampEntryOffset + 8 ) <= t_TimestampTableEndOffset )
  872. {
  873. t_TimestampEntryOffset += 8 ;
  874. }
  875. else
  876. {
  877. break;
  878. }
  879. }
  880. else
  881. {
  882. t_TimestampEntryOffset += 4 ;
  883. }
  884. a_TimestampCount++ ;
  885. }
  886. // Extract the entries
  887. if (a_TimestampCount > 0)
  888. {
  889. a_TimestampRoute = new ULONG[a_TimestampCount];
  890. a_Timestamp = new ULONG[a_TimestampCount];
  891. a_TimestampCount = 0;
  892. t_TimestampEntryOffset = 5 ;
  893. while ( ( t_TimestampEntryOffset + 3 ) < t_TimestampTableEndOffset )
  894. {
  895. if (( t_AddressMode ) && ( ( t_TimestampEntryOffset + 8 ) <= t_TimestampTableEndOffset ))
  896. {
  897. // a_TimestampRoute[a_TimestampCount] = * ( ( IPAddr * ) ( t_OptionPtr + t_TimestampEntryOffset - 1 ) ) ;
  898. memcpy ( &a_TimestampRoute[a_TimestampCount], t_OptionPtr + t_TimestampEntryOffset - 1, sizeof ( IPAddr ) );
  899. t_TimestampEntryOffset += 4 ;
  900. }
  901. else
  902. {
  903. a_TimestampRoute[a_TimestampCount] = 0;
  904. }
  905. // a_Timestamp[a_TimestampCount++] = * ( ( ULONG * ) ( t_OptionPtr + t_TimestampEntryOffset - 1 ) ) ;
  906. memcpy ( &a_Timestamp[a_TimestampCount++], t_OptionPtr + t_TimestampEntryOffset - 1, sizeof ( ULONG ) );
  907. t_TimestampEntryOffset += 4 ;
  908. }
  909. }
  910. t_OptionPtr += t_OptionLength ;
  911. }
  912. else
  913. {
  914. // INVALID_RR_OPTION
  915. t_Done = TRUE ;
  916. t_Result = WBEM_E_FAILED ;
  917. }
  918. }
  919. else
  920. {
  921. // INVALID_TS_OPTION
  922. t_Done = TRUE ;
  923. t_Result = WBEM_E_FAILED ;
  924. }
  925. }
  926. break;
  927. default:
  928. {
  929. if ( ( t_OptionPtr + 2 ) > t_EndPtr )
  930. {
  931. t_Done = TRUE ;
  932. }
  933. else
  934. {
  935. t_OptionPtr += t_OptionPtr [ 1 ] ;
  936. }
  937. }
  938. break;
  939. }
  940. }
  941. }
  942. catch (...)
  943. {
  944. if (a_RouteSource != NULL)
  945. {
  946. delete [] a_RouteSource;
  947. a_RouteSource = NULL;
  948. }
  949. if (a_TimestampRoute != NULL)
  950. {
  951. delete [] a_TimestampRoute;
  952. a_TimestampRoute = NULL;
  953. }
  954. if (a_Timestamp != NULL)
  955. {
  956. delete [] a_Timestamp;
  957. a_Timestamp = NULL;
  958. }
  959. throw;
  960. }
  961. if (FAILED(t_Result))
  962. {
  963. if (a_RouteSource != NULL)
  964. {
  965. delete [] a_RouteSource;
  966. a_RouteSource = NULL;
  967. }
  968. if (a_TimestampRoute != NULL)
  969. {
  970. delete [] a_TimestampRoute;
  971. a_TimestampRoute = NULL;
  972. }
  973. if (a_Timestamp != NULL)
  974. {
  975. delete [] a_Timestamp;
  976. a_Timestamp = NULL;
  977. }
  978. }
  979. return t_Result ;
  980. }
  981. HRESULT CPingTaskObject::Icmp_RequestResponse (
  982. LPCWSTR a_AddressString ,
  983. ULONG a_Address ,
  984. ULONG a_TimeToLive ,
  985. ULONG a_Timeout ,
  986. ULONG a_SendSize ,
  987. BOOL a_NoFragmentation ,
  988. ULONG a_TypeofService ,
  989. ULONG a_RecordRoute ,
  990. ULONG a_TimestampRoute ,
  991. ULONG a_SourceRouteType ,
  992. LPCWSTR a_SourceRoute,
  993. BOOL a_ResolveAddress,
  994. ULONG a_ResolveError
  995. )
  996. {
  997. HRESULT t_Result = S_OK ;
  998. CPingCallBackObject *t_Ctxt = new CPingCallBackObject(
  999. this,
  1000. a_AddressString,
  1001. a_Address,
  1002. a_TimeToLive,
  1003. a_Timeout,
  1004. a_SendSize,
  1005. a_NoFragmentation,
  1006. a_TypeofService,
  1007. a_RecordRoute,
  1008. a_TimestampRoute,
  1009. a_SourceRouteType,
  1010. a_SourceRoute,
  1011. a_ResolveAddress,
  1012. a_ResolveError
  1013. );
  1014. t_Ctxt->AddRef();
  1015. try
  1016. {
  1017. if (a_ResolveError == 0)
  1018. {
  1019. //attach t_Ctxt to thread and make the thread do a
  1020. //t_Ctxt->SendEcho();
  1021. BOOL t_Sent = FALSE;
  1022. WmiStatusCode t_StatusCode = t_Ctxt->Initialize () ;
  1023. if (t_StatusCode == e_StatusCode_Success )
  1024. {
  1025. t_StatusCode = CPingProvider :: s_PingThread->EnQueue (0 , *t_Ctxt) ;
  1026. if (t_StatusCode == e_StatusCode_Success )
  1027. {
  1028. t_Sent = TRUE;
  1029. }
  1030. }
  1031. if (!t_Sent)
  1032. {
  1033. t_Result = WBEM_E_FAILED ;
  1034. SetErrorInfo(IDS_ICMPECHO ,
  1035. WBEM_E_FAILED ) ;
  1036. try
  1037. {
  1038. t_Ctxt->Release();
  1039. }
  1040. catch(...)
  1041. {
  1042. t_Ctxt = NULL;
  1043. throw;
  1044. }
  1045. }
  1046. }
  1047. else
  1048. {
  1049. t_Result = Icmp_IndicateResolveError(t_Ctxt);
  1050. t_Ctxt->Disconnect();
  1051. t_Ctxt->Release();
  1052. t_Ctxt = NULL;
  1053. if (SUCCEEDED(t_Result))
  1054. {
  1055. DecrementPingCount();
  1056. }
  1057. }
  1058. }
  1059. catch (...)
  1060. {
  1061. t_Ctxt->Release();
  1062. throw;
  1063. }
  1064. return t_Result ;
  1065. }