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.

759 lines
17 KiB

  1. /*++
  2. Copyright (c) 1999, Microsoft Corporation
  3. Module Name:
  4. sample\configurationentry.c
  5. Abstract:
  6. The file contains functions to deal with the configuration entry.
  7. --*/
  8. #include "pchsample.h"
  9. #pragma hdrstop
  10. static
  11. VOID
  12. DisplayEventEntry (
  13. IN PQUEUE_ENTRY pqeEntry)
  14. /*++
  15. Routine Description
  16. Displays an EVENT_ENTRY object.
  17. Locks
  18. None
  19. Arguments
  20. pqeEntry address of the 'leEventQueueLink' field
  21. Return Value
  22. None
  23. --*/
  24. {
  25. EE_Display(CONTAINING_RECORD(pqeEntry, EVENT_ENTRY, qeEventQueueLink));
  26. }
  27. static
  28. VOID
  29. FreeEventEntry (
  30. IN PQUEUE_ENTRY pqeEntry)
  31. /*++
  32. Routine Description
  33. Frees an EVENT_ENTRY object.
  34. Locks
  35. None
  36. Arguments
  37. pqeEntry address of the 'leEventQueueLink' field
  38. Return Value
  39. None
  40. --*/
  41. {
  42. EE_Destroy(CONTAINING_RECORD(pqeEntry, EVENT_ENTRY, qeEventQueueLink));
  43. }
  44. DWORD
  45. EE_Create (
  46. IN ROUTING_PROTOCOL_EVENTS rpeEvent,
  47. IN MESSAGE mMessage,
  48. OUT PEVENT_ENTRY *ppeeEventEntry)
  49. /*++
  50. Routine Description
  51. Creates an event entry.
  52. Locks
  53. None
  54. Arguments
  55. rpeEvent
  56. mMessage
  57. ppEventEntry pointer to the event entry address
  58. Return Value
  59. NO_ERROR if success
  60. Failure code o/w
  61. --*/
  62. {
  63. DWORD dwErr = NO_ERROR;
  64. PEVENT_ENTRY peeEntry; // scratch
  65. // validate parameters
  66. if (!ppeeEventEntry)
  67. return ERROR_INVALID_PARAMETER;
  68. *ppeeEventEntry = NULL;
  69. // allocate the interface entry structure
  70. MALLOC(&peeEntry, sizeof(EVENT_ENTRY), &dwErr);
  71. if (dwErr != NO_ERROR)
  72. return dwErr;
  73. // initialize various fields
  74. InitializeQueueHead(&(peeEntry->qeEventQueueLink));
  75. peeEntry->rpeEvent = rpeEvent;
  76. peeEntry->mMessage = mMessage;
  77. *ppeeEventEntry = peeEntry;
  78. return dwErr;
  79. }
  80. DWORD
  81. EE_Destroy (
  82. IN PEVENT_ENTRY peeEventEntry)
  83. /*++
  84. Routine Description
  85. Destroys an event entry.
  86. Locks
  87. None.
  88. Arguments
  89. peeEventEntry pointer to the event entry
  90. Return Value
  91. NO_ERROR always
  92. --*/
  93. {
  94. if (!peeEventEntry)
  95. return NO_ERROR;
  96. FREE(peeEventEntry);
  97. return NO_ERROR;
  98. }
  99. #ifdef DEBUG
  100. DWORD
  101. EE_Display (
  102. IN PEVENT_ENTRY peeEventEntry)
  103. /*++
  104. Routine Description
  105. Displays an event entry.
  106. Locks
  107. None.
  108. Arguments
  109. peeEventEntry pointer to the event entry
  110. Return Value
  111. NO_ERROR always
  112. --*/
  113. {
  114. if (!peeEventEntry)
  115. return NO_ERROR;
  116. TRACE1(CONFIGURATION,
  117. "Event %u",
  118. peeEventEntry->rpeEvent);
  119. if (peeEventEntry->rpeEvent is SAVE_INTERFACE_CONFIG_INFO)
  120. TRACE1(CONFIGURATION,
  121. "Index %u",
  122. (peeEventEntry->mMessage).InterfaceIndex);
  123. return NO_ERROR;
  124. }
  125. #endif // DEBUG
  126. DWORD
  127. EnqueueEvent(
  128. IN ROUTING_PROTOCOL_EVENTS rpeEvent,
  129. IN MESSAGE mMessage)
  130. /*++
  131. Routine Description
  132. Queues an event entry in g_ce.lqEventQueue.
  133. Locks
  134. Locks and unlocks the locked queue g_ce.lqEventQueue.
  135. Arguments
  136. rpeEvent
  137. mMessage
  138. Return Value
  139. NO_ERROR success
  140. Error Code o/w
  141. --*/
  142. {
  143. DWORD dwErr = NO_ERROR;
  144. PEVENT_ENTRY peeEntry = NULL;
  145. dwErr = EE_Create(rpeEvent, mMessage, &peeEntry);
  146. // destroyed in EE_DequeueEvent
  147. if (dwErr is NO_ERROR)
  148. {
  149. ACQUIRE_QUEUE_LOCK(&(g_ce.lqEventQueue));
  150. Enqueue(&(g_ce.lqEventQueue.head), &(peeEntry->qeEventQueueLink));
  151. RELEASE_QUEUE_LOCK(&(g_ce.lqEventQueue));
  152. }
  153. return dwErr;
  154. }
  155. DWORD
  156. DequeueEvent(
  157. OUT ROUTING_PROTOCOL_EVENTS *prpeEvent,
  158. OUT MESSAGE *pmMessage)
  159. /*++
  160. Routine Description
  161. Dequeues an event entry from g_ce.lqEventQueue.
  162. Locks
  163. Locks and unlocks the locked queue g_ce.lqEventQueue.
  164. Arguments
  165. prpeEvent
  166. pmMessage
  167. Return Value
  168. NO_ERROR success
  169. ERROR_NO_MORE_ITEMS o/w
  170. --*/
  171. {
  172. DWORD dwErr = NO_ERROR;
  173. PQUEUE_ENTRY pqe = NULL;
  174. PEVENT_ENTRY pee = NULL;
  175. ACQUIRE_QUEUE_LOCK(&(g_ce.lqEventQueue));
  176. do // breakout loop
  177. {
  178. if (IsQueueEmpty(&(g_ce.lqEventQueue.head)))
  179. {
  180. dwErr = ERROR_NO_MORE_ITEMS;
  181. TRACE0(CONFIGURATION, "Error no events in the queue");
  182. LOGWARN0(EVENT_QUEUE_EMPTY, dwErr);
  183. break;
  184. }
  185. pqe = Dequeue(&(g_ce.lqEventQueue.head));
  186. pee = CONTAINING_RECORD(pqe, EVENT_ENTRY, qeEventQueueLink);
  187. *(prpeEvent) = pee->rpeEvent;
  188. *(pmMessage) = pee->mMessage;
  189. // created in EE_EnqueueEvent
  190. EE_Destroy(pee);
  191. pee = NULL;
  192. } while (FALSE);
  193. RELEASE_QUEUE_LOCK(&(g_ce.lqEventQueue));
  194. return dwErr;
  195. }
  196. DWORD
  197. CE_Create (
  198. IN PCONFIGURATION_ENTRY pce)
  199. /*++
  200. Routine Description
  201. Creates a configuration entry on DLL_PROCESS_ATTACH.
  202. Locks
  203. None
  204. Arguments
  205. pce pointer to the configuration entry
  206. Return Value
  207. NO_ERROR if success
  208. Failure code o/w
  209. --*/
  210. {
  211. DWORD dwErr = NO_ERROR;
  212. // initialize to default values
  213. ZeroMemory(pce, sizeof(CONFIGURATION_ENTRY));
  214. pce->dwTraceID = INVALID_TRACEID;
  215. do // breakout loop
  216. {
  217. // initialize the read-write lock
  218. CREATE_READ_WRITE_LOCK(&(pce->rwlLock));
  219. if (!READ_WRITE_LOCK_CREATED(&(pce->rwlLock)))
  220. {
  221. dwErr = GetLastError();
  222. TRACE1(CONFIGURATION, "Error %u creating read-write-lock", dwErr);
  223. LOGERR0(CREATE_RWL_FAILED, dwErr);
  224. break;
  225. }
  226. // initialize the global heap
  227. pce->hGlobalHeap = HeapCreate(0, 0, 0);
  228. if (pce->hGlobalHeap is NULL)
  229. {
  230. dwErr = GetLastError();
  231. TRACE1(CONFIGURATION, "Error %u creating global heap", dwErr);
  232. LOGERR0(HEAP_CREATE_FAILED, dwErr);
  233. break;
  234. }
  235. //
  236. // initialize the count of threads that are active in IPSAMPLE
  237. // create the semaphore released by each thread when it is done
  238. // required for clean stop to the protocol
  239. //
  240. pce->ulActivityCount = 0;
  241. pce->hActivitySemaphore = CreateSemaphore(NULL, 0, 0xfffffff, NULL);
  242. if (pce->hActivitySemaphore is NULL)
  243. {
  244. dwErr = GetLastError();
  245. TRACE1(CONFIGURATION, "Error %u creating semaphore", dwErr);
  246. LOGERR0(CREATE_SEMAPHORE_FAILED, dwErr);
  247. break;
  248. }
  249. // Logging & Tracing Information
  250. pce->dwLogLevel = IPSAMPLE_LOGGING_INFO;
  251. pce->hLogHandle = RouterLogRegister("IPSAMPLE");
  252. pce->dwTraceID = TraceRegister("IPSAMPLE");
  253. // Event Queue
  254. INITIALIZE_LOCKED_QUEUE(&(pce->lqEventQueue));
  255. if (!LOCKED_QUEUE_INITIALIZED(&(pce->lqEventQueue)))
  256. {
  257. dwErr = GetLastError();
  258. TRACE1(CONFIGURATION, "Error %u initializing locked queue", dwErr);
  259. LOGERR0(INIT_CRITSEC_FAILED, dwErr);
  260. break;
  261. }
  262. // Protocol State
  263. pce->iscStatus = IPSAMPLE_STATUS_STOPPED;
  264. // Store of Dynamic Locks
  265. // pce->dlsDynamicLocksStore zero'ed out
  266. // Timer Entry
  267. // pce->hTimerQueue = NULL;
  268. // Router Manager Information (later)
  269. // pce->hMgrNotificationEvent = NULL
  270. // pce->sfSupportFunctions zero'ed out
  271. // RTMv2 Information
  272. // pce->reiRtmEntity zero'ed out
  273. // pce->rrpRtmProfile zero'ed out
  274. // pce->hRtmHandle = NULL
  275. // pce->hRtmNotificationHandle = NULL
  276. // MGM Information
  277. // pce->hMgmHandle = NULL
  278. // Network Entry
  279. // pce->pneNetworkEntry = NULL;
  280. // Global Statistics
  281. // pce->igsStats zero'ed out
  282. } while (FALSE);
  283. if (dwErr != NO_ERROR)
  284. {
  285. // something went wrong, so cleanup.
  286. TRACE0(CONFIGURATION, "Failed to create configuration entry");
  287. CE_Destroy(pce);
  288. }
  289. return dwErr;
  290. }
  291. DWORD
  292. CE_Destroy (
  293. IN PCONFIGURATION_ENTRY pce)
  294. /*++
  295. Routine Description
  296. Destroys a configuration entry on DLL_PROCESS_DEATTACH
  297. Locks
  298. Assumes exclusive access to rwlLock with no waiting thread.
  299. Arguments
  300. pce pointer to the configuration entry
  301. Return Value
  302. NO_ERROR always
  303. --*/
  304. {
  305. // Network Entry
  306. // MGM Information
  307. // RTMv2 Information
  308. // Router Manager Information
  309. // Timer Entry
  310. // Store of Dynamic Locks
  311. // protocol state should be such...
  312. RTASSERT(pce->iscStatus is IPSAMPLE_STATUS_STOPPED);
  313. // Event Queue
  314. if (LOCKED_QUEUE_INITIALIZED(&(pce->lqEventQueue)))
  315. DELETE_LOCKED_QUEUE((&(pce->lqEventQueue)), FreeEventEntry);
  316. // Logging & Tracing Information
  317. if (pce->dwTraceID != INVALID_TRACEID)
  318. {
  319. TraceDeregister(pce->dwTraceID);
  320. pce->dwTraceID = INVALID_TRACEID;
  321. }
  322. if (pce->hLogHandle != NULL)
  323. {
  324. RouterLogDeregister(pce->hLogHandle);
  325. pce->hLogHandle = NULL;
  326. }
  327. // destroy the semaphore released by each thread when it is done
  328. if (pce->hActivitySemaphore != NULL)
  329. {
  330. CloseHandle(pce->hActivitySemaphore);
  331. pce->hActivitySemaphore = NULL;
  332. }
  333. if (pce->hGlobalHeap != NULL)
  334. {
  335. HeapDestroy(pce->hGlobalHeap);
  336. pce->hGlobalHeap = NULL;
  337. }
  338. // delete the read-write lock
  339. if (READ_WRITE_LOCK_CREATED(&(pce->rwlLock)))
  340. DELETE_READ_WRITE_LOCK(&(pce->rwlLock));
  341. return NO_ERROR;
  342. }
  343. DWORD
  344. CE_Initialize (
  345. IN PCONFIGURATION_ENTRY pce,
  346. IN HANDLE hMgrNotificationEvent,
  347. IN PSUPPORT_FUNCTIONS psfSupportFunctions,
  348. IN PIPSAMPLE_GLOBAL_CONFIG pigc)
  349. /*++
  350. Routine Description
  351. Initializes a configuration entry on StartProtocol.
  352. Locks
  353. Assumes exclusive access to pce->rwlLock
  354. Arguments
  355. pce pointer to the configuration entry
  356. hMgrNotificationEvent event used to notify ip router manager
  357. psfSupportFunctions functions exported by ip router manager
  358. pigc global configuration set in registry
  359. Return Value
  360. NO_ERROR if success
  361. Failure code o/w
  362. --*/
  363. {
  364. WORD wVersionRequested = MAKEWORD(1,1);
  365. WSADATA wsaData;
  366. BOOL bCleanupWinsock = FALSE;
  367. DWORD dwErr = NO_ERROR;
  368. // validate environment
  369. RTASSERT(pce->ulActivityCount is 0);
  370. RTASSERT(pce->iscStatus is IPSAMPLE_STATUS_STOPPED);
  371. do // breakout loop
  372. {
  373. pce->ulActivityCount = 0;
  374. pce->dwLogLevel = pigc->dwLoggingLevel;
  375. dwErr = (DWORD) WSAStartup(wVersionRequested, &wsaData);
  376. if (dwErr != 0)
  377. {
  378. TRACE1(CONFIGURATION, "Error %u starting windows sockets", dwErr);
  379. LOGERR0(WSASTARTUP_FAILED, dwErr);
  380. break;
  381. }
  382. bCleanupWinsock = TRUE;
  383. // Store of Dynamic Locks
  384. dwErr = InitializeDynamicLocksStore(&(pce->dlsDynamicLocksStore),
  385. GLOBAL_HEAP);
  386. if (dwErr != NO_ERROR)
  387. {
  388. TRACE1(CONFIGURATION, "Error %u initializing locks store", dwErr);
  389. LOGERR0(INIT_CRITSEC_FAILED, dwErr);
  390. break;
  391. }
  392. // Timer Entry
  393. pce->hTimerQueue = CreateTimerQueue();
  394. if (!pce->hTimerQueue)
  395. {
  396. dwErr = GetLastError();
  397. TRACE1(CONFIGURATION, "Error %u registering timer queue", dwErr);
  398. LOGERR0(CREATE_TIMER_QUEUE_FAILED, dwErr);
  399. break;
  400. }
  401. // Router Manager Information
  402. pce->hMgrNotificationEvent = hMgrNotificationEvent;
  403. if (psfSupportFunctions)
  404. pce->sfSupportFunctions = *psfSupportFunctions;
  405. // RTMv2 Information
  406. pce->reiRtmEntity.RtmInstanceId = 0;
  407. pce->reiRtmEntity.AddressFamily = AF_INET;
  408. pce->reiRtmEntity.EntityId.EntityProtocolId = PROTO_IP_SAMPLE;
  409. pce->reiRtmEntity.EntityId.EntityInstanceId = 0;
  410. dwErr = RTM_RegisterEntity(
  411. &pce->reiRtmEntity, // IN my RTM_ENTITY_INFO
  412. NULL, // IN my exported methods
  413. RTM_CallbackEvent, // IN my callback function
  414. TRUE, // IN reserve opaque pointer?
  415. &pce->rrpRtmProfile, // OUT my RTM_REGN_PROFILE
  416. &pce->hRtmHandle); // OUT my RTMv2 handle
  417. if (dwErr != NO_ERROR)
  418. {
  419. TRACE1(CONFIGURATION, "Error %u registering with RTM", dwErr);
  420. LOGERR0(RTM_REGISTER_FAILED, dwErr);
  421. break;
  422. }
  423. dwErr = RTM_RegisterForChangeNotification(
  424. pce->hRtmHandle, // IN my RTMv2 handle
  425. RTM_VIEW_MASK_MCAST, // IN route table views relevant to moi
  426. RTM_CHANGE_TYPE_BEST, // IN change types interesting to moi
  427. NULL, // IN context in callback function
  428. &pce->hRtmNotificationHandle); // OUT my notification handle
  429. if (dwErr != NO_ERROR)
  430. {
  431. TRACE1(CONFIGURATION,
  432. "Error %u registering for change with RTM", dwErr);
  433. LOGERR0(RTM_REGISTER_FAILED, dwErr);
  434. break;
  435. }
  436. // MGM Information
  437. // pce->hMgmHandle (later)
  438. // Network Entry
  439. dwErr = NE_Create(&(pce->pneNetworkEntry));
  440. if (dwErr != NO_ERROR)
  441. break;
  442. // Global Statistics
  443. ZeroMemory(&(pce->igsStats), sizeof(IPSAMPLE_GLOBAL_STATS));
  444. pce->iscStatus = IPSAMPLE_STATUS_RUNNING;
  445. } while (FALSE);
  446. // something went wrong, cleanup
  447. if (dwErr != NO_ERROR)
  448. CE_Cleanup(pce, bCleanupWinsock);
  449. return dwErr;
  450. }
  451. DWORD
  452. CE_Cleanup (
  453. IN PCONFIGURATION_ENTRY pce,
  454. IN BOOL bCleanupWinsock)
  455. /*++
  456. Routine Description
  457. Cleans up a configuration entry on StopProtocol.
  458. Locks
  459. Exclusive access to pce->rwlLock by virtue of no competing threads.
  460. NOTE: However, pce->rwlLock should NOT actually be held! The call to
  461. DeleteTimerQueueEx blocks till all queued callbacks finish execution.
  462. These callbacks may acquire pce->rwlLock, causing deadlock.
  463. Arguments
  464. pce pointer to the configuration entry
  465. bCleanupWinsock
  466. Return Value
  467. NO_ERROR always
  468. --*/
  469. {
  470. DWORD dwErr = NO_ERROR;
  471. // Network Entry
  472. NE_Destroy(pce->pneNetworkEntry);
  473. pce->pneNetworkEntry = NULL;
  474. // MGM Information (later)
  475. pce->hMgmHandle = NULL;
  476. // RTMv2 Information
  477. if (pce->hRtmNotificationHandle)
  478. {
  479. dwErr = RTM_DeregisterFromChangeNotification(
  480. pce->hRtmHandle,
  481. pce->hRtmNotificationHandle);
  482. if (dwErr != NO_ERROR)
  483. TRACE1(CONFIGURATION,
  484. "Error %u deregistering for change from RTM", dwErr);
  485. }
  486. pce->hRtmNotificationHandle = NULL;
  487. if (pce->hRtmHandle)
  488. {
  489. dwErr = RTM_DeregisterEntity(pce->hRtmHandle);
  490. if (dwErr != NO_ERROR)
  491. TRACE1(CONFIGURATION,
  492. "Error %u deregistering from RTM", dwErr);
  493. }
  494. pce->hRtmHandle = NULL;
  495. // Router Manager Information
  496. // valid till overwritten, needed to signal the ip router manager
  497. // pce->hMgrNotificationEvent
  498. // pce->sfSupportFunctions
  499. // Timer Entry
  500. if (pce->hTimerQueue)
  501. DeleteTimerQueueEx(pce->hTimerQueue, INVALID_HANDLE_VALUE);
  502. pce->hTimerQueue = NULL;
  503. // Store of Dynamic Locks
  504. if (DYNAMIC_LOCKS_STORE_INITIALIZED(&(pce->dlsDynamicLocksStore)))
  505. {
  506. dwErr = DeInitializeDynamicLocksStore(&(pce->dlsDynamicLocksStore));
  507. // all dynamic locks should have been free
  508. RTASSERT(dwErr is NO_ERROR);
  509. }
  510. if (bCleanupWinsock)
  511. WSACleanup();
  512. // protocol state
  513. pce->iscStatus = IPSAMPLE_STATUS_STOPPED;
  514. return NO_ERROR;
  515. }
  516. #ifdef DEBUG
  517. DWORD
  518. CE_Display (
  519. IN PCONFIGURATION_ENTRY pce)
  520. /*++
  521. Routine Description
  522. Displays a configuration entry.
  523. Locks
  524. Acquires shared pce->rwlLock
  525. Releases pce->rwlLock
  526. Arguments
  527. pce pointer to the configuration entry to be displayed
  528. Return Value
  529. NO_ERROR always
  530. --*/
  531. {
  532. if (!pce)
  533. return NO_ERROR;
  534. ACQUIRE_READ_LOCK(&(pce->rwlLock));
  535. TRACE0(CONFIGURATION, "Configuration Entry...");
  536. TRACE3(CONFIGURATION,
  537. "ActivityCount %u, LogLevel %u, NumInterfaces %u",
  538. pce->ulActivityCount,
  539. pce->dwLogLevel,
  540. pce->igsStats.ulNumInterfaces);
  541. NE_Display(pce->pneNetworkEntry);
  542. RELEASE_READ_LOCK(&(pce->rwlLock));
  543. TRACE0(CONFIGURATION, "EventQueue...");
  544. ACQUIRE_QUEUE_LOCK(&(pce->lqEventQueue));
  545. MapCarQueue(&((pce->lqEventQueue).head), DisplayEventEntry);
  546. RELEASE_QUEUE_LOCK(&(pce->lqEventQueue));
  547. return NO_ERROR;
  548. }
  549. #endif // DEBUG