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.

593 lines
14 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1997 - 1999
  3. Module Name:
  4. dest.cxx
  5. Abstract:
  6. Code to keep track of reachability of the list destinations specified
  7. in Event System's Reachability Event subscriptions.
  8. Author:
  9. Gopal Parupudi <GopalP>
  10. [Notes:]
  11. optional-notes
  12. Revision History:
  13. GopalP 10/31/1997 Start.
  14. --*/
  15. #include <precomp.hxx>
  16. //
  17. // Constants
  18. //
  19. #define SENS_REACHABILITY_POLLING_INTERVAL 5*60*1000 // 5 minutes
  20. #define SENS_REACHABILITY_FIRST_SCAN_TIME 5*60*1000 // 5 minutes
  21. //
  22. // Globals
  23. //
  24. LIST *gpReachList;
  25. HANDLE ghReachTimer;
  26. BOOL
  27. StartReachabilityEngine(
  28. void
  29. )
  30. /*++
  31. Routine Description:
  32. Start the Destination reachability engine.
  33. Arguments:
  34. None.
  35. Return Value:
  36. TRUE, if successful.
  37. FALSE, otherwise.
  38. --*/
  39. {
  40. BOOL bRetVal;
  41. bRetVal = TRUE; // Note it is TRUE, by default.
  42. SensPrintA(SENS_INFO, ("StartReachabilityEngine(): Starting...\n"));
  43. RequestSensLock();
  44. if (ghReachTimer != NULL)
  45. {
  46. SensPrintA(SENS_INFO, ("StartReachabilityEngine(): Engine "
  47. "already started!\n"));
  48. goto Cleanup;
  49. }
  50. //
  51. // Create a timer object to poll for destination reachability
  52. //
  53. SensSetTimerQueueTimer(
  54. bRetVal, // Bool return on NT5
  55. ghReachTimer, // Handle return on IE5
  56. NULL, // Use default process timer queue
  57. ReachabilityPollingRoutine, // Callback
  58. NULL, // Parameter
  59. SENS_REACHABILITY_FIRST_SCAN_TIME, // Time from now when timer should fire
  60. SENS_REACHABILITY_POLLING_INTERVAL,// Time inbetween firings of this timer
  61. 0x0 // No Flags.
  62. );
  63. if (SENS_TIMER_CREATE_FAILED(bRetVal, ghReachTimer))
  64. {
  65. SensPrintA(SENS_INFO, ("StartReachabilityEngine(): SensCancelTimerQueueTimer("
  66. "Reachability) failed!\n"));
  67. bRetVal = FALSE;
  68. goto Cleanup;
  69. }
  70. Cleanup:
  71. //
  72. // Cleanup
  73. //
  74. ReleaseSensLock();
  75. SensPrintA(SENS_INFO, ("StartReachabilityEngine(): Returning %s\n",
  76. bRetVal ? "TRUE" : "FALSE"));
  77. return bRetVal;
  78. }
  79. BOOL
  80. StopReachabilityEngine(
  81. void
  82. )
  83. /*++
  84. Routine Description:
  85. Start the Destination reachability engine.
  86. Arguments:
  87. None.
  88. Return Value:
  89. TRUE, if successful.
  90. FALSE, otherwise.
  91. --*/
  92. {
  93. BOOL bStatus;
  94. bStatus = TRUE; // Note it is TRUE, by default.
  95. SensPrintA(SENS_INFO, ("StopReachabilityEngine(): Stopping...\n"));
  96. RequestSensLock();
  97. //
  98. // Remove Reachability polling timer
  99. //
  100. if (NULL != ghReachTimer)
  101. {
  102. bStatus = SensCancelTimerQueueTimer(NULL, ghReachTimer, NULL);
  103. ghReachTimer = NULL;
  104. SensPrintA(SENS_INFO, ("StopReachabilityEngine(): SensCancelTimerQueueTimer("
  105. "Reachability) %s\n", bStatus ? "succeeded" : "failed!"));
  106. }
  107. ReleaseSensLock();
  108. SensPrintA(SENS_INFO, ("StopReachabilityEngine(): Returning %s\n",
  109. bStatus ? "TRUE" : "FALSE"));
  110. return bStatus;
  111. }
  112. BOOL
  113. InitReachabilityEngine(
  114. void
  115. )
  116. /*++
  117. Routine Description:
  118. Initialize the Reachability polling mechanism.
  119. Arguments:
  120. None.
  121. Return Value:
  122. TRUE, if successful.
  123. FALSE, otherwise.
  124. --*/
  125. {
  126. BOOL bRetVal;
  127. bRetVal = FALSE;
  128. //
  129. // Initialize the list of destinations
  130. //
  131. gpReachList = new LIST();
  132. if (NULL == gpReachList)
  133. {
  134. goto Cleanup;
  135. }
  136. bRetVal = StartReachabilityEngine();
  137. Cleanup:
  138. //
  139. // Cleanup
  140. //
  141. return bRetVal;
  142. }
  143. SENS_TIMER_CALLBACK_RETURN
  144. ReachabilityPollingRoutine(
  145. PVOID pvIgnore,
  146. BOOLEAN bIgnore
  147. )
  148. /*++
  149. Routine Description:
  150. This routine is called periodically to walk through the reachability list
  151. to see if the destinations are reachable.
  152. Arguments:
  153. pvIgnore - Ignored.
  154. bIgnore - Ignored.
  155. Return Value:
  156. None.
  157. --*/
  158. {
  159. PNODE pTemp;
  160. DWORD OldState;
  161. QOCINFO DestQOCInfo;
  162. DWORD dwLastError;
  163. char *DestinationA;
  164. static BOOL bGotDestinations = FALSE;
  165. //
  166. // Get the list of destinations, if necessary.
  167. //
  168. if (FALSE == bGotDestinations)
  169. {
  170. HRESULT hr;
  171. hr = GetDestinationsFromSubscriptions();
  172. if (SUCCEEDED(hr))
  173. {
  174. bGotDestinations = TRUE;
  175. }
  176. else
  177. {
  178. SensPrintA(SENS_ERR, ("InitReachabilityPolling(): GetDestinations"
  179. "FromSubscriptions() failed with 0x%x.\n", hr));
  180. }
  181. }
  182. SensPrintA(SENS_INFO, ("ReachabilityPollingRoutine(): Checking "
  183. "Destinations for reachability.\n"));
  184. // PERF NOTE: Critsec held too long!
  185. gpReachList->RequestLock();
  186. if (gpReachList->IsEmpty() == TRUE)
  187. {
  188. StopReachabilityEngine();
  189. gpReachList->ReleaseLock();
  190. return;
  191. }
  192. //
  193. // Loop through all destinations checking for reachability.
  194. //
  195. pTemp = gpReachList->pHead;
  196. while (pTemp != NULL)
  197. {
  198. error_status_t status;
  199. // Save old reachability state.
  200. OldState = pTemp->State;
  201. //
  202. // Is it Reachable?
  203. //
  204. dwLastError = ERROR_SUCCESS;
  205. DestQOCInfo.dwSize = sizeof(QOCINFO);
  206. status = RPC_IsDestinationReachableW(
  207. NULL,
  208. pTemp->Destination,
  209. &DestQOCInfo,
  210. (LPBOOL) &pTemp->State,
  211. &dwLastError
  212. );
  213. ASSERT(status == RPC_S_OK);
  214. if ( (pTemp->State != OldState)
  215. && (dwLastError == ERROR_SUCCESS))
  216. {
  217. // Fire the Event!
  218. SENSEVENT_REACH Data;
  219. Data.eType = SENS_EVENT_REACH;
  220. Data.bReachable = pTemp->State;
  221. Data.Destination = pTemp->Destination;
  222. memcpy(&Data.QocInfo, &DestQOCInfo, DestQOCInfo.dwSize);
  223. // NOTE: Set the following field appropriately. This is the best we can do.
  224. Data.strConnection = DEFAULT_LAN_CONNECTION_NAME;
  225. SensFireEvent((PVOID)&Data);
  226. }
  227. if (dwLastError != ERROR_SUCCESS)
  228. {
  229. SensPrintW(SENS_INFO, (L"ReachabilityPollingRoutine(): %s is not reachable - %d\n",
  230. pTemp->Destination, dwLastError));
  231. if (ERROR_INVALID_PARAMETER == dwLastError)
  232. {
  233. // Remove the destination from further reachability checks.
  234. gpReachList->DeleteByDest(pTemp->Destination);
  235. }
  236. }
  237. pTemp = pTemp->Next;
  238. } // while()
  239. gpReachList->ReleaseLock();
  240. //
  241. // Dump the list
  242. //
  243. gpReachList->Print();
  244. }
  245. HRESULT
  246. GetDestinationsFromSubscriptions(
  247. void
  248. )
  249. /*++
  250. Routine Description:
  251. Retrieve the names of destinations from Reachability subscriptions and
  252. insert into the Reachability List.
  253. Arguments:
  254. None.
  255. Return Value:
  256. S_OK, on success.
  257. HRESULT, on failure.
  258. --*/
  259. {
  260. HRESULT hr;
  261. int errorIndex;
  262. LONG lCount;
  263. BSTR bstrPropertyName;
  264. BSTR bstrEventClassID;
  265. VARIANT variantPropertyValue;
  266. WCHAR wszQuery[MAX_QUERY_SIZE];
  267. LPOLESTR strGuid;
  268. IEventSystem *pIEventSystem;
  269. IEventSubscription *pIEventSubscription;
  270. IEventObjectCollection *pSubscriptionCollection;
  271. IEnumEventObject *pIEnumEventObject;
  272. hr = S_OK;
  273. lCount = 0;
  274. errorIndex = 0;
  275. strGuid = NULL;
  276. bstrPropertyName = NULL;
  277. bstrEventClassID = NULL;
  278. pIEventSystem = NULL;
  279. pIEventSubscription = NULL;
  280. pSubscriptionCollection = NULL;
  281. pIEnumEventObject = NULL;
  282. // Get a new IEventSystem object to play with.
  283. hr = CoCreateInstance(
  284. CLSID_CEventSystem,
  285. NULL,
  286. CLSCTX_SERVER,
  287. IID_IEventSystem,
  288. (LPVOID *) &pIEventSystem
  289. );
  290. if (FAILED(hr))
  291. {
  292. SensPrint(SENS_ERR, (SENS_STRING("GetDestinationsFromSubscriptions(): failed to create ")
  293. SENS_STRING("IEventSystem - hr = <%x>\n"), hr));
  294. goto Cleanup;
  295. }
  296. //
  297. // Form the query.
  298. //
  299. // (EventClassID = NetEventClassID) AND
  300. // ( (MethodName = 'DestinationReachable')
  301. // OR (MethodName = 'DestinationReachableNoQocInfo'))
  302. //
  303. AllocateBstrFromGuid(bstrEventClassID, SENSGUID_EVENTCLASS_NETWORK);
  304. StringCchCopy(wszQuery, MAX_QUERY_SIZE, SENS_BSTR("(EventClassID="));
  305. StringCchCat(wszQuery, MAX_QUERY_SIZE, bstrEventClassID);
  306. StringCchCat(wszQuery, MAX_QUERY_SIZE, SENS_BSTR(") AND ( (MethodName = \'"));
  307. StringCchCat(wszQuery, MAX_QUERY_SIZE, DESTINATION_REACHABLE_METHOD);
  308. StringCchCat(wszQuery, MAX_QUERY_SIZE, SENS_BSTR("\') OR (MethodName = \'"));
  309. StringCchCat(wszQuery, MAX_QUERY_SIZE, DESTINATION_REACHABLE_NOQOC_METHOD);
  310. StringCchCat(wszQuery, MAX_QUERY_SIZE, SENS_BSTR("\'))"));
  311. hr = pIEventSystem->Query(
  312. PROGID_EventSubscriptionCollection,
  313. wszQuery,
  314. &errorIndex,
  315. (LPUNKNOWN *) &pSubscriptionCollection
  316. );
  317. if (FAILED(hr))
  318. {
  319. SensPrint(SENS_ERR, (SENS_STRING("GetDestinationsFromSubscriptions(): failed to Query() ")
  320. SENS_STRING("- hr = <%x>\n"), hr));
  321. SensPrint(SENS_ERR, (SENS_STRING("errorIndex = %d\n"), errorIndex));
  322. goto Cleanup;
  323. }
  324. SensPrint(SENS_ERR, (SENS_STRING("Query = %s, hr = 0x%x\n"), wszQuery, hr));
  325. #if DBG
  326. hr = pSubscriptionCollection->get_Count(&lCount);
  327. if (FAILED(hr))
  328. {
  329. SensPrint(SENS_ERR, (SENS_STRING("GetDestinationsFromSubscriptions(): ")
  330. SENS_STRING("get_Count() returned hr = <%x>\n"), hr));
  331. goto Cleanup;
  332. }
  333. SensPrint(SENS_ERR, (SENS_STRING("GetDestinationsFromSubscriptions(): ")
  334. SENS_STRING("Found %d Reachability subscriptions.\n"), lCount));
  335. if (0 == lCount)
  336. {
  337. goto Cleanup;
  338. }
  339. #endif // DBG
  340. // Get a new Enum object to play with.
  341. hr = pSubscriptionCollection->get_NewEnum(
  342. (IEnumEventObject **) &pIEnumEventObject
  343. );
  344. if (FAILED(hr))
  345. {
  346. SensPrint(SENS_ERR, (SENS_STRING("GetDestinationsFromSubscriptions(): ")
  347. SENS_STRING("get_NewEnum() returned hr = <%x>\n"), hr));
  348. goto Cleanup;
  349. }
  350. hr = S_OK;
  351. hr = pIEnumEventObject->Reset();
  352. //
  353. // Extract each destination name and insert into list.
  354. //
  355. while (S_OK == hr)
  356. {
  357. ULONG cElements = 1;
  358. hr = pIEnumEventObject->Next(
  359. cElements,
  360. (LPUNKNOWN *) &pIEventSubscription,
  361. &cElements
  362. );
  363. if ( (S_OK != hr)
  364. || (1 != cElements))
  365. {
  366. SensPrint(SENS_ERR, (SENS_STRING("GetDestinationsFromSubscriptions(): ")
  367. SENS_STRING("Next() failed hr = <%x>, count = %d\n"), hr, cElements));
  368. goto Cleanup;
  369. }
  370. //
  371. // Try to get the value for Publisher property - bstrDestination
  372. //
  373. VariantInit(&variantPropertyValue);
  374. AllocateBstrFromString(bstrPropertyName, PROPERTY_DESTINATION);
  375. hr = pIEventSubscription->GetPublisherProperty(
  376. bstrPropertyName,
  377. &variantPropertyValue
  378. );
  379. if (hr == S_OK)
  380. {
  381. // Found the property!
  382. gpReachList->InsertByDest(variantPropertyValue.bstrVal);
  383. SensPrint(SENS_ERR, (SENS_STRING("GetDestinationsFromSubscriptions(): ")
  384. SENS_STRING("Added to Reachability List: %s\n"),
  385. variantPropertyValue.bstrVal));
  386. goto ProcessNextSubscription;
  387. }
  388. //
  389. // Now, try to get the value for Publisher property - bstrDestinationNoQOC
  390. //
  391. FreeBstr(bstrPropertyName);
  392. VariantInit(&variantPropertyValue);
  393. AllocateBstrFromString(bstrPropertyName, PROPERTY_DESTINATION_NOQOC);
  394. hr = pIEventSubscription->GetPublisherProperty(
  395. bstrPropertyName,
  396. &variantPropertyValue
  397. );
  398. if (hr == S_OK)
  399. {
  400. // Found the property!
  401. gpReachList->InsertByDest(variantPropertyValue.bstrVal);
  402. SensPrint(SENS_ERR, (SENS_STRING("GetDestinationsFromSubscriptions(): ")
  403. SENS_STRING("Added to Reachability List: %s\n"),
  404. variantPropertyValue.bstrVal));
  405. goto ProcessNextSubscription;
  406. }
  407. SensPrint(SENS_ERR, (SENS_STRING("GetDestinationsFromSubscriptions(): failed to get ")
  408. SENS_STRING("PublisherProperty - hr = <%x>\n"), hr));
  409. ProcessNextSubscription:
  410. VariantClear(&variantPropertyValue);
  411. FreeBstr(bstrPropertyName);
  412. pIEventSubscription->Release();
  413. pIEventSubscription = NULL;
  414. hr = S_OK;
  415. } // while()
  416. Cleanup:
  417. //
  418. // Cleanup
  419. //
  420. if (pIEventSystem)
  421. {
  422. pIEventSystem->Release();
  423. }
  424. if (pIEventSubscription)
  425. {
  426. pIEventSubscription->Release();
  427. }
  428. if (pSubscriptionCollection)
  429. {
  430. pSubscriptionCollection->Release();
  431. }
  432. if (pIEnumEventObject)
  433. {
  434. pIEnumEventObject->Release();
  435. }
  436. FreeBstr(bstrEventClassID);
  437. FreeStr(strGuid);
  438. return (hr);
  439. }