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.

1695 lines
41 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. notify.c
  5. Abstract:
  6. Server side support for the notification APIs in the NT Cluster Service
  7. Author:
  8. John Vert (jvert) 26-Mar-1996
  9. Revision History:
  10. --*/
  11. #include "apip.h"
  12. //
  13. // Classification of the item types based on FilterType
  14. //
  15. #define ITEM_TYPE_OBJECT_NAME (CLUSTER_CHANGE_GROUP_STATE | \
  16. CLUSTER_CHANGE_GROUP_ADDED | \
  17. CLUSTER_CHANGE_GROUP_DELETED | \
  18. CLUSTER_CHANGE_GROUP_PROPERTY | \
  19. CLUSTER_CHANGE_NODE_STATE | \
  20. CLUSTER_CHANGE_NODE_DELETED | \
  21. CLUSTER_CHANGE_NODE_ADDED | \
  22. CLUSTER_CHANGE_NODE_PROPERTY | \
  23. CLUSTER_CHANGE_RESOURCE_STATE | \
  24. CLUSTER_CHANGE_RESOURCE_ADDED | \
  25. CLUSTER_CHANGE_RESOURCE_DELETED | \
  26. CLUSTER_CHANGE_RESOURCE_PROPERTY | \
  27. CLUSTER_CHANGE_NETWORK_STATE | \
  28. CLUSTER_CHANGE_NETWORK_ADDED | \
  29. CLUSTER_CHANGE_NETWORK_DELETED | \
  30. CLUSTER_CHANGE_NETWORK_PROPERTY | \
  31. CLUSTER_CHANGE_NETINTERFACE_STATE | \
  32. CLUSTER_CHANGE_NETINTERFACE_ADDED | \
  33. CLUSTER_CHANGE_NETINTERFACE_DELETED | \
  34. CLUSTER_CHANGE_NETINTERFACE_PROPERTY)
  35. #define ITEM_TYPE_OBJECT_ID (CLUSTER_CHANGE_RESOURCE_TYPE_DELETED | \
  36. CLUSTER_CHANGE_RESOURCE_TYPE_ADDED | \
  37. CLUSTER_CHANGE_QUORUM_STATE | \
  38. CLUSTER_CHANGE_CLUSTER_STATE)
  39. #define ITEM_TYPE_REGISTRY (CLUSTER_CHANGE_REGISTRY_NAME | \
  40. CLUSTER_CHANGE_REGISTRY_ATTRIBUTES | \
  41. CLUSTER_CHANGE_REGISTRY_VALUE | \
  42. CLUSTER_CHANGE_REGISTRY_SUBTREE)
  43. #define ITEM_TYPE_NAME (ITEM_TYPE_REGISTRY | \
  44. CLUSTER_CHANGE_HANDLE_CLOSE | \
  45. CLUSTER_CHANGE_CLUSTER_PROPERTY)
  46. //
  47. // Define types local to this module
  48. //
  49. typedef struct _INTEREST {
  50. LIST_ENTRY ListEntry;
  51. LIST_ENTRY HandleList;
  52. PVOID Object;
  53. DWORD Filter;
  54. DWORD Key;
  55. } INTEREST, *PINTEREST;
  56. typedef struct _ITEM {
  57. LIST_ENTRY ListEntry;
  58. DWORD FilterType;
  59. DWORD NotifyKey;
  60. union {
  61. LPVOID Object;
  62. WCHAR KeyName[0]; // For registry notifications
  63. };
  64. } ITEM, *PITEM;
  65. //
  66. // Function prototypes local to this module
  67. //
  68. DWORD
  69. ApipAddNotifyInterest(
  70. IN PNOTIFY_PORT Notify,
  71. IN PAPI_HANDLE ObjectHandle,
  72. IN DWORD Filter,
  73. IN DWORD NotifyKey,
  74. IN DWORD NotifyFilter
  75. );
  76. //
  77. // Define static data local to this module
  78. //
  79. LIST_ENTRY NotifyListHead;
  80. CRITICAL_SECTION NotifyListLock;
  81. VOID
  82. ApiReportRegistryNotify(
  83. IN DWORD_PTR Context1,
  84. IN DWORD_PTR Context2,
  85. IN DWORD CompletionFilter,
  86. IN LPCWSTR KeyName
  87. )
  88. /*++
  89. Routine Description:
  90. Interface to be called by DM when a registry change triggers
  91. a notification.
  92. Arguments:
  93. Context1 - Supplies the first DWORD of Context that was passed
  94. to DmNotifyChangeKey. This is the NOTIFY_PORT to be used.
  95. Context2 - Supplies the second DWORD of Context that was passed
  96. to DmNotifyChangeKey. This is the NotifyKey to be used.
  97. CompletionFilter - Supplies the type of change that occurred.
  98. KeyName - Supplies the relative name of the key that was changed.
  99. Return Value:
  100. None.
  101. --*/
  102. {
  103. PLIST_ENTRY InterestEntry;
  104. PLIST_ENTRY PortEntry;
  105. PINTEREST Interest;
  106. PITEM Item;
  107. PNOTIFY_PORT NotifyPort;
  108. DWORD NameLength;
  109. ClRtlLogPrint(LOG_NOISE,
  110. "[API] Notification on port %1!8lx!, key %2!8lx! of type %3!d!. KeyName %4!ws!\n",
  111. (DWORD)Context1,
  112. (DWORD)Context2,
  113. CompletionFilter,
  114. KeyName);
  115. NameLength = (lstrlenW(KeyName)+1)*sizeof(WCHAR);
  116. NotifyPort = (PNOTIFY_PORT)Context1;
  117. //
  118. // Post notification item for this interest.
  119. //
  120. Item = LocalAlloc(LMEM_FIXED, sizeof(ITEM)+NameLength);
  121. if (Item != NULL) {
  122. Item->FilterType = CompletionFilter;
  123. Item->NotifyKey = (DWORD)Context2;
  124. CopyMemory(Item->KeyName, KeyName, NameLength);
  125. ClRtlInsertTailQueue(&NotifyPort->Queue, &Item->ListEntry);
  126. }
  127. }
  128. VOID
  129. ApipRundownNotify(
  130. IN PAPI_HANDLE Handle
  131. )
  132. /*++
  133. Routine Description:
  134. Runs down any notification interests on a particular
  135. cluster object. The INTEREST structures will be yanked
  136. from their notification lists and freed.
  137. Arguments:
  138. Handle - Supplies the API handle for the object.
  139. Return Value:
  140. None.
  141. --*/
  142. {
  143. PLIST_ENTRY ListEntry;
  144. PINTEREST Interest;
  145. if (IsListEmpty(&Handle->NotifyList)) {
  146. return;
  147. }
  148. EnterCriticalSection(&NotifyListLock);
  149. while (!IsListEmpty(&Handle->NotifyList)) {
  150. ListEntry = RemoveHeadList(&Handle->NotifyList);
  151. Interest = CONTAINING_RECORD(ListEntry,
  152. INTEREST,
  153. HandleList);
  154. CL_ASSERT(Interest->Object == Handle->Cluster);
  155. RemoveEntryList(&Interest->ListEntry);
  156. LocalFree(Interest);
  157. }
  158. LeaveCriticalSection(&NotifyListLock);
  159. }
  160. DWORD
  161. WINAPI
  162. ApipEventHandler(
  163. IN CLUSTER_EVENT Event,
  164. IN PVOID Context
  165. )
  166. /*++
  167. Routine Description:
  168. Processes cluster events and dispatches the notifications to the appropriate
  169. notify queues.
  170. Arguments:
  171. Event - Supplies the type of cluster event.
  172. Context - Supplies the event-specific context
  173. Return Value:
  174. ERROR_SUCCESS
  175. --*/
  176. {
  177. DWORD Filter;
  178. DWORD NameLength = 0;
  179. PLIST_ENTRY PortEntry;
  180. PNOTIFY_PORT NotifyPort;
  181. PLIST_ENTRY InterestEntry;
  182. PINTEREST Interest;
  183. PITEM Item;
  184. //
  185. // Translate EP event types into clusapi notification filters
  186. //
  187. switch (Event) {
  188. case CLUSTER_EVENT_API_NODE_UP:
  189. case CLUSTER_EVENT_NODE_DOWN:
  190. case CLUSTER_EVENT_NODE_JOIN:
  191. case CLUSTER_EVENT_NODE_CHANGE:
  192. Filter = CLUSTER_CHANGE_NODE_STATE;
  193. break;
  194. case CLUSTER_EVENT_NODE_ADDED:
  195. Filter = CLUSTER_CHANGE_NODE_ADDED;
  196. break;
  197. case CLUSTER_EVENT_NODE_PROPERTY_CHANGE:
  198. Filter = CLUSTER_CHANGE_NODE_PROPERTY;
  199. break;
  200. case CLUSTER_EVENT_NODE_DELETED:
  201. Filter = CLUSTER_CHANGE_NODE_DELETED;
  202. break;
  203. case CLUSTER_EVENT_RESOURCE_ONLINE:
  204. case CLUSTER_EVENT_RESOURCE_OFFLINE:
  205. case CLUSTER_EVENT_RESOURCE_FAILED:
  206. case CLUSTER_EVENT_RESOURCE_CHANGE:
  207. Filter = CLUSTER_CHANGE_RESOURCE_STATE;
  208. break;
  209. case CLUSTER_EVENT_RESOURCE_PROPERTY_CHANGE:
  210. Filter = CLUSTER_CHANGE_RESOURCE_PROPERTY;
  211. break;
  212. case CLUSTER_EVENT_RESOURCE_ADDED:
  213. Filter = CLUSTER_CHANGE_RESOURCE_ADDED;
  214. break;
  215. case CLUSTER_EVENT_RESOURCE_DELETED:
  216. Filter = CLUSTER_CHANGE_RESOURCE_DELETED;
  217. break;
  218. case CLUSTER_EVENT_GROUP_ONLINE:
  219. case CLUSTER_EVENT_GROUP_OFFLINE:
  220. case CLUSTER_EVENT_GROUP_FAILED:
  221. case CLUSTER_EVENT_GROUP_CHANGE:
  222. Filter = CLUSTER_CHANGE_GROUP_STATE;
  223. break;
  224. case CLUSTER_EVENT_GROUP_PROPERTY_CHANGE:
  225. Filter = CLUSTER_CHANGE_GROUP_PROPERTY;
  226. break;
  227. case CLUSTER_EVENT_GROUP_ADDED:
  228. Filter = CLUSTER_CHANGE_GROUP_ADDED;
  229. break;
  230. case CLUSTER_EVENT_GROUP_DELETED:
  231. Filter = CLUSTER_CHANGE_GROUP_DELETED;
  232. break;
  233. case CLUSTER_EVENT_NETWORK_UNAVAILABLE:
  234. case CLUSTER_EVENT_NETWORK_DOWN:
  235. case CLUSTER_EVENT_NETWORK_PARTITIONED:
  236. case CLUSTER_EVENT_NETWORK_UP:
  237. Filter = CLUSTER_CHANGE_NETWORK_STATE;
  238. break;
  239. case CLUSTER_EVENT_NETWORK_PROPERTY_CHANGE:
  240. Filter = CLUSTER_CHANGE_NETWORK_PROPERTY;
  241. break;
  242. case CLUSTER_EVENT_NETWORK_ADDED:
  243. Filter = CLUSTER_CHANGE_NETWORK_ADDED;
  244. break;
  245. case CLUSTER_EVENT_NETWORK_DELETED:
  246. Filter = CLUSTER_CHANGE_NETWORK_DELETED;
  247. break;
  248. case CLUSTER_EVENT_NETINTERFACE_UNAVAILABLE:
  249. case CLUSTER_EVENT_NETINTERFACE_FAILED:
  250. case CLUSTER_EVENT_NETINTERFACE_UNREACHABLE:
  251. case CLUSTER_EVENT_NETINTERFACE_UP:
  252. Filter = CLUSTER_CHANGE_NETINTERFACE_STATE;
  253. break;
  254. case CLUSTER_EVENT_NETINTERFACE_PROPERTY_CHANGE:
  255. Filter = CLUSTER_CHANGE_NETINTERFACE_PROPERTY;
  256. break;
  257. case CLUSTER_EVENT_NETINTERFACE_ADDED:
  258. Filter = CLUSTER_CHANGE_NETINTERFACE_ADDED;
  259. break;
  260. case CLUSTER_EVENT_NETINTERFACE_DELETED:
  261. Filter = CLUSTER_CHANGE_NETINTERFACE_DELETED;
  262. break;
  263. case CLUSTER_EVENT_RESTYPE_ADDED:
  264. Filter = CLUSTER_CHANGE_RESOURCE_TYPE_ADDED;
  265. break;
  266. case CLUSTER_EVENT_RESTYPE_DELETED:
  267. Filter = CLUSTER_CHANGE_RESOURCE_TYPE_DELETED;
  268. break;
  269. case CLUSTER_EVENT_PROPERTY_CHANGE:
  270. Filter = CLUSTER_CHANGE_CLUSTER_PROPERTY;
  271. break;
  272. default:
  273. //
  274. // No notification for any of the other events yet.
  275. //
  276. return(ERROR_SUCCESS);
  277. }
  278. //
  279. // Run through the outstanding notify sessions and post notify items
  280. // for any matches.
  281. //
  282. EnterCriticalSection(&NotifyListLock);
  283. PortEntry = NotifyListHead.Flink;
  284. while (PortEntry != &NotifyListHead) {
  285. NotifyPort = CONTAINING_RECORD(PortEntry, NOTIFY_PORT, ListEntry);
  286. if (NotifyPort->Filter & Filter) {
  287. //
  288. // There are notification interests for this notify type, run
  289. // through the list of notification interests.
  290. //
  291. InterestEntry = NotifyPort->InterestList.Flink;
  292. while (InterestEntry != &NotifyPort->InterestList) {
  293. Interest = CONTAINING_RECORD(InterestEntry, INTEREST, ListEntry);
  294. //
  295. // Report the notification if the Interest's cluster object is NULL (which
  296. // means that this is a general cluster interest) or if the interest's specific
  297. // object matches the object reporting the notify.
  298. //
  299. if ((Interest->Filter & Filter) &&
  300. ((Interest->Object == NULL) ||
  301. (Interest->Object == Context))) {
  302. //
  303. // Post notification item for this interest.
  304. //
  305. if (Filter & ITEM_TYPE_NAME) {
  306. NameLength = (lstrlenW(Context)+1)*sizeof(WCHAR);
  307. Item = LocalAlloc(LMEM_FIXED, sizeof(ITEM)+NameLength);
  308. } else {
  309. Item = LocalAlloc(LMEM_FIXED, sizeof(ITEM));
  310. }
  311. if (Item != NULL) {
  312. Item->FilterType = Filter;
  313. Item->NotifyKey = Interest->Key;
  314. if (!(Filter & ITEM_TYPE_NAME)) {
  315. //
  316. // Reference the object again to ensure that the name does
  317. // not disappear out from under us before we are done with it.
  318. //
  319. Item->Object = Context;
  320. OmReferenceObject(Context);
  321. } else {
  322. CopyMemory(Item->KeyName, Context, NameLength);
  323. }
  324. ClRtlInsertTailQueue(&NotifyPort->Queue, &Item->ListEntry);
  325. }
  326. }
  327. InterestEntry = InterestEntry->Flink;
  328. }
  329. }
  330. PortEntry = PortEntry->Flink;
  331. }
  332. LeaveCriticalSection(&NotifyListLock);
  333. return(ERROR_SUCCESS);
  334. }
  335. HNOTIFY_RPC
  336. s_ApiCreateNotify(
  337. IN HCLUSTER_RPC hCluster,
  338. OUT error_status_t *rpc_error
  339. )
  340. /*++
  341. Routine Description:
  342. Creates the server side of a notification port.
  343. Arguments:
  344. IDL_handle - Supplies cluster handle.
  345. dwFilter - Supplies the cluster events of interest.
  346. dwNotifyKey - Supplies a key to be returned on any notifications
  347. rpc_error - Returns any RPC-specific error
  348. Return Value:
  349. An RPC context handle for a notification port.
  350. NULL on failure.
  351. --*/
  352. {
  353. DWORD Status;
  354. PNOTIFY_PORT Port;
  355. PAPI_HANDLE Handle;
  356. if (ApiState != ApiStateOnline) {
  357. *rpc_error = ERROR_SHARING_PAUSED;
  358. return(NULL);
  359. }
  360. Handle = LocalAlloc(LMEM_FIXED, sizeof(API_HANDLE));
  361. if (Handle == NULL) {
  362. *rpc_error = ERROR_NOT_ENOUGH_MEMORY;
  363. return(NULL);
  364. }
  365. Port = LocalAlloc(LMEM_FIXED, sizeof(NOTIFY_PORT));
  366. if (Port == NULL) {
  367. LocalFree(Handle);
  368. *rpc_error = ERROR_NOT_ENOUGH_MEMORY;
  369. return(NULL);
  370. }
  371. InitializeListHead(&Port->InterestList);
  372. InitializeListHead(&Port->RegistryList);
  373. InitializeCriticalSection(&Port->Lock);
  374. Status = ClRtlInitializeQueue(&Port->Queue);
  375. if (Status != ERROR_SUCCESS) {
  376. LocalFree(Port);
  377. *rpc_error = Status;
  378. return(NULL);
  379. }
  380. EnterCriticalSection(&NotifyListLock);
  381. InsertTailList(&NotifyListHead, &Port->ListEntry);
  382. LeaveCriticalSection(&NotifyListLock);
  383. Handle->Type = API_NOTIFY_HANDLE;
  384. Handle->Notify = Port;
  385. Handle->Flags = 0;
  386. InitializeListHead(&Handle->NotifyList);
  387. *rpc_error = ERROR_SUCCESS;
  388. return(Handle);
  389. }
  390. error_status_t
  391. s_ApiAddNotifyCluster(
  392. IN HNOTIFY_RPC hNotify,
  393. IN HCLUSTER_RPC hCluster,
  394. IN DWORD dwFilter,
  395. IN DWORD dwNotifyKey
  396. )
  397. /*++
  398. Routine Description:
  399. Adds another set of notification events to an existing
  400. cluster notification port
  401. Arguments:
  402. hNotify - Supplies the notification port
  403. hCluster - Supplies the cluster to be added
  404. dwFilter - Supplies the set of notification events to be added.
  405. dwNotifyKey - Supplies the notification key to be returned on
  406. any notification events
  407. Return Value:
  408. ERROR_SUCCESS if successful
  409. Win32 error code otherwise.
  410. --*/
  411. {
  412. DWORD Status;
  413. PNOTIFY_PORT Port;
  414. PAPI_HANDLE Handle;
  415. API_ASSERT_INIT();
  416. VALIDATE_NOTIFY(Port, hNotify);
  417. Handle = (PAPI_HANDLE)hCluster;
  418. if (Handle->Type != API_CLUSTER_HANDLE) {
  419. return(ERROR_INVALID_HANDLE);
  420. }
  421. Status = ApipAddNotifyInterest(Port,
  422. Handle,
  423. dwFilter,
  424. dwNotifyKey,
  425. 0);
  426. if (dwFilter & ITEM_TYPE_REGISTRY) {
  427. //
  428. // Add a registry notification for the entire cluster.
  429. //
  430. DmNotifyChangeKey(DmClusterParametersKey,
  431. dwFilter & ITEM_TYPE_REGISTRY,
  432. (dwFilter & CLUSTER_CHANGE_REGISTRY_SUBTREE) ? TRUE : FALSE,
  433. &Port->RegistryList,
  434. ApiReportRegistryNotify,
  435. (DWORD_PTR)Port,
  436. dwNotifyKey);
  437. }
  438. return(Status);
  439. }
  440. error_status_t
  441. s_ApiAddNotifyNode(
  442. IN HNOTIFY_RPC hNotify,
  443. IN HNODE_RPC hNode,
  444. IN DWORD dwFilter,
  445. IN DWORD dwNotifyKey,
  446. OUT DWORD *dwStateSequence
  447. )
  448. /*++
  449. Routine Description:
  450. Adds a node-specific notification event to an existing
  451. cluster notification port
  452. Arguments:
  453. hNotify - Supplies the notification port
  454. hNode - Supplies the node to be added
  455. dwFilter - Supplies the set of notification events to be added.
  456. dwNotifyKey - Supplies the notification key to be returned on
  457. any notification events for this node
  458. dwStateSequence - Returns the current state sequence for the
  459. specified object
  460. Return Value:
  461. ERROR_SUCCESS if successful
  462. Win32 error code otherwise.
  463. --*/
  464. {
  465. DWORD Status;
  466. PNOTIFY_PORT Port;
  467. PNM_NODE Node;
  468. API_ASSERT_INIT();
  469. VALIDATE_NOTIFY(Port, hNotify);
  470. VALIDATE_NODE(Node, hNode);
  471. Status = ApipAddNotifyInterest(Port,
  472. (PAPI_HANDLE)hNode,
  473. dwFilter,
  474. dwNotifyKey,
  475. 0);
  476. if (Status == ERROR_SUCCESS) {
  477. *dwStateSequence = NmGetNodeState(Node);
  478. }
  479. return(Status);
  480. }
  481. error_status_t
  482. s_ApiAddNotifyGroup(
  483. IN HNOTIFY_RPC hNotify,
  484. IN HGROUP_RPC hGroup,
  485. IN DWORD dwFilter,
  486. IN DWORD dwNotifyKey,
  487. OUT DWORD *dwStateSequence
  488. )
  489. /*++
  490. Routine Description:
  491. Adds a group-specific notification event to an existing
  492. cluster notification port
  493. Arguments:
  494. hNotify - Supplies the notification port
  495. hGroup - Supplies the group to be added
  496. dwFilter - Supplies the set of notification events to be added.
  497. dwNotifyKey - Supplies the notification key to be returned on
  498. any notification events for this group
  499. dwStateSequence - Returns the current state sequence for the
  500. specified object
  501. Return Value:
  502. ERROR_SUCCESS if successful
  503. Win32 error code otherwise.
  504. --*/
  505. {
  506. DWORD Status;
  507. PNOTIFY_PORT Port;
  508. PFM_GROUP Group;
  509. API_ASSERT_INIT();
  510. VALIDATE_NOTIFY(Port, hNotify);
  511. VALIDATE_GROUP_EXISTS(Group, hGroup);
  512. Status = ApipAddNotifyInterest(Port,
  513. (PAPI_HANDLE)hGroup,
  514. dwFilter,
  515. dwNotifyKey,
  516. 0);
  517. if (Status == ERROR_SUCCESS) {
  518. *dwStateSequence = Group->StateSequence;
  519. }
  520. return(Status);
  521. }
  522. error_status_t
  523. s_ApiAddNotifyNetwork(
  524. IN HNOTIFY_RPC hNotify,
  525. IN HNETWORK_RPC hNetwork,
  526. IN DWORD dwFilter,
  527. IN DWORD dwNotifyKey,
  528. OUT DWORD *dwStateSequence
  529. )
  530. /*++
  531. Routine Description:
  532. Adds a network-specific notification event to an existing
  533. cluster notification port
  534. Arguments:
  535. hNotify - Supplies the notification port
  536. hNetwork - Supplies the network to be added
  537. dwFilter - Supplies the set of notification events to be added.
  538. dwNotifyKey - Supplies the notification key to be returned on
  539. any notification events for this network
  540. dwStateSequence - Returns the current state sequence for the
  541. specified object
  542. Return Value:
  543. ERROR_SUCCESS if successful
  544. Win32 error code otherwise.
  545. --*/
  546. {
  547. DWORD Status;
  548. PNOTIFY_PORT Port;
  549. PNM_NETWORK Network;
  550. API_ASSERT_INIT();
  551. VALIDATE_NOTIFY(Port, hNotify);
  552. VALIDATE_NETWORK_EXISTS(Network, hNetwork);
  553. Status = ApipAddNotifyInterest(Port,
  554. (PAPI_HANDLE)hNetwork,
  555. dwFilter,
  556. dwNotifyKey,
  557. 0);
  558. if (Status == ERROR_SUCCESS) {
  559. *dwStateSequence = NmGetNetworkState( Network );
  560. }
  561. return(Status);
  562. }
  563. error_status_t
  564. s_ApiAddNotifyNetInterface(
  565. IN HNOTIFY_RPC hNotify,
  566. IN HNETINTERFACE_RPC hNetInterface,
  567. IN DWORD dwFilter,
  568. IN DWORD dwNotifyKey,
  569. OUT DWORD *dwStateSequence
  570. )
  571. /*++
  572. Routine Description:
  573. Adds a network interface-specific notification event to an existing
  574. cluster notification port
  575. Arguments:
  576. hNotify - Supplies the notification port
  577. hNetInterface - Supplies the network interface to be added
  578. dwFilter - Supplies the set of notification events to be added.
  579. dwNotifyKey - Supplies the notification key to be returned on
  580. any notification events for this network
  581. dwStateSequence - Returns the current state sequence for the
  582. specified object
  583. Return Value:
  584. ERROR_SUCCESS if successful
  585. Win32 error code otherwise.
  586. --*/
  587. {
  588. DWORD Status;
  589. PNOTIFY_PORT Port;
  590. PNM_INTERFACE NetInterface;
  591. API_ASSERT_INIT();
  592. VALIDATE_NOTIFY(Port, hNotify);
  593. VALIDATE_NETINTERFACE_EXISTS(NetInterface, hNetInterface);
  594. Status = ApipAddNotifyInterest(Port,
  595. (PAPI_HANDLE)hNetInterface,
  596. dwFilter,
  597. dwNotifyKey,
  598. 0);
  599. if (Status == ERROR_SUCCESS) {
  600. *dwStateSequence = NmGetInterfaceState( NetInterface );
  601. }
  602. return(Status);
  603. }
  604. error_status_t
  605. s_ApiAddNotifyResource(
  606. IN HNOTIFY_RPC hNotify,
  607. IN HRES_RPC hResource,
  608. IN DWORD dwFilter,
  609. IN DWORD dwNotifyKey,
  610. OUT DWORD *dwStateSequence
  611. )
  612. /*++
  613. Routine Description:
  614. Adds a resource-specific notification event to an existing
  615. cluster notification port
  616. Arguments:
  617. hNotify - Supplies the notification port
  618. hResource - Supplies the resource to be added
  619. dwFilter - Supplies the set of notification events to be added.
  620. dwNotifyKey - Supplies the notification key to be returned on
  621. any notification events for this group
  622. dwStateSequence - Returns the current state sequence for the
  623. specified object
  624. Return Value:
  625. ERROR_SUCCESS if successful
  626. Win32 error code otherwise.
  627. --*/
  628. {
  629. DWORD Status;
  630. PNOTIFY_PORT Port;
  631. PFM_RESOURCE Resource;
  632. API_ASSERT_INIT();
  633. VALIDATE_NOTIFY(Port, hNotify);
  634. VALIDATE_RESOURCE_EXISTS(Resource, hResource);
  635. Status = ApipAddNotifyInterest(Port,
  636. (PAPI_HANDLE)hResource,
  637. dwFilter,
  638. dwNotifyKey,
  639. 0);
  640. if (Status == ERROR_SUCCESS) {
  641. *dwStateSequence = Resource->StateSequence;
  642. }
  643. return(Status);
  644. }
  645. error_status_t
  646. s_ApiReAddNotifyNode(
  647. IN HNOTIFY_RPC hNotify,
  648. IN HNODE_RPC hNode,
  649. IN DWORD dwFilter,
  650. IN DWORD dwNotifyKey,
  651. IN DWORD dwStateSequence
  652. )
  653. /*++
  654. Routine Description:
  655. Adds a node-specific notification event to an existing
  656. cluster notification port
  657. Arguments:
  658. hNotify - Supplies the notification port
  659. hNode - Supplies the node to be added
  660. dwFilter - Supplies the set of notification events to be added.
  661. dwNotifyKey - Supplies the notification key to be returned on
  662. any notification events for this node
  663. dwStateSequence - Supplies the previous state sequence. If this does
  664. not match the current sequence, an immediate notification will
  665. be issued.
  666. Return Value:
  667. ERROR_SUCCESS if successful
  668. Win32 error code otherwise.
  669. --*/
  670. {
  671. DWORD Status;
  672. PNOTIFY_PORT Port;
  673. PNM_NODE Node;
  674. DWORD NotifyFilter;
  675. API_ASSERT_INIT();
  676. VALIDATE_NOTIFY(Port, hNotify);
  677. VALIDATE_NODE(Node, hNode);
  678. ClRtlLogPrint(LOG_NOISE,
  679. "[API] s_ApiReAddNotifyNode for %1!ws! (%2!lx!) oldstate %3!d! newstate %4!d!\n",
  680. OmObjectId(Node),
  681. dwFilter,
  682. dwStateSequence,
  683. NmGetNodeState(Node));
  684. if (NmGetNodeState(Node) != (CLUSTER_NODE_STATE)dwStateSequence) {
  685. NotifyFilter = CLUSTER_CHANGE_NODE_STATE & dwFilter;
  686. } else {
  687. NotifyFilter = 0;
  688. }
  689. Status = ApipAddNotifyInterest(Port,
  690. (PAPI_HANDLE)hNode,
  691. dwFilter,
  692. dwNotifyKey,
  693. NotifyFilter);
  694. return(Status);
  695. }
  696. error_status_t
  697. s_ApiReAddNotifyGroup(
  698. IN HNOTIFY_RPC hNotify,
  699. IN HGROUP_RPC hGroup,
  700. IN DWORD dwFilter,
  701. IN DWORD dwNotifyKey,
  702. IN DWORD dwStateSequence
  703. )
  704. /*++
  705. Routine Description:
  706. Adds a group-specific notification event to an existing
  707. cluster notification port
  708. Arguments:
  709. hNotify - Supplies the notification port
  710. hGroup - Supplies the group to be added
  711. dwFilter - Supplies the set of notification events to be added.
  712. dwNotifyKey - Supplies the notification key to be returned on
  713. any notification events for this group
  714. Return Value:
  715. ERROR_SUCCESS if successful
  716. Win32 error code otherwise.
  717. --*/
  718. {
  719. DWORD Status;
  720. PNOTIFY_PORT Port;
  721. PFM_GROUP Group;
  722. DWORD NotifyFilter;
  723. API_ASSERT_INIT();
  724. VALIDATE_NOTIFY(Port, hNotify);
  725. VALIDATE_GROUP_EXISTS(Group, hGroup);
  726. ClRtlLogPrint(LOG_NOISE,
  727. "[API] s_ApiReAddNotifyGroup for %1!ws! (%2!lx!) oldstate %3!d! newstate %4!d!\n",
  728. OmObjectName(Group),
  729. dwFilter,
  730. dwStateSequence,
  731. Group->StateSequence);
  732. if (Group->StateSequence != dwStateSequence) {
  733. NotifyFilter = CLUSTER_CHANGE_GROUP_STATE & dwFilter;
  734. } else {
  735. NotifyFilter = 0;
  736. }
  737. Status = ApipAddNotifyInterest(Port,
  738. (PAPI_HANDLE)hGroup,
  739. dwFilter,
  740. dwNotifyKey,
  741. NotifyFilter);
  742. return(Status);
  743. }
  744. error_status_t
  745. s_ApiReAddNotifyNetwork(
  746. IN HNOTIFY_RPC hNotify,
  747. IN HNETWORK_RPC hNetwork,
  748. IN DWORD dwFilter,
  749. IN DWORD dwNotifyKey,
  750. IN DWORD dwStateSequence
  751. )
  752. /*++
  753. Routine Description:
  754. Adds a network-specific notification event to an existing
  755. cluster notification port
  756. Arguments:
  757. hNotify - Supplies the notification port
  758. hNetwork - Supplies the network to be added
  759. dwFilter - Supplies the set of notification events to be added.
  760. dwNotifyKey - Supplies the notification key to be returned on
  761. any notification events for this network
  762. Return Value:
  763. ERROR_SUCCESS if successful
  764. Win32 error code otherwise.
  765. --*/
  766. {
  767. DWORD Status;
  768. PNOTIFY_PORT Port;
  769. PNM_NETWORK Network;
  770. DWORD NotifyFilter = 0;
  771. CLUSTER_NETWORK_STATE CurrentState;
  772. API_ASSERT_INIT();
  773. VALIDATE_NOTIFY(Port, hNotify);
  774. VALIDATE_NETWORK_EXISTS(Network, hNetwork);
  775. CurrentState = NmGetNetworkState( Network );
  776. ClRtlLogPrint(LOG_NOISE,
  777. "[API] s_ApiReAddNotifyNetwork for %1!ws! (%2!lx!) oldstate %3!d! newstate %4!d!\n",
  778. OmObjectName(Network),
  779. dwFilter,
  780. dwStateSequence,
  781. CurrentState);
  782. if ((DWORD)CurrentState != dwStateSequence) {
  783. NotifyFilter = CLUSTER_CHANGE_NETWORK_STATE & dwFilter;
  784. } else {
  785. NotifyFilter = 0;
  786. }
  787. Status = ApipAddNotifyInterest(Port,
  788. (PAPI_HANDLE)hNetwork,
  789. dwFilter,
  790. dwNotifyKey,
  791. NotifyFilter);
  792. return(Status);
  793. }
  794. error_status_t
  795. s_ApiReAddNotifyNetInterface(
  796. IN HNOTIFY_RPC hNotify,
  797. IN HNETINTERFACE_RPC hNetInterface,
  798. IN DWORD dwFilter,
  799. IN DWORD dwNotifyKey,
  800. IN DWORD dwStateSequence
  801. )
  802. /*++
  803. Routine Description:
  804. Adds a network interface-specific notification event to an existing
  805. cluster notification port
  806. Arguments:
  807. hNotify - Supplies the notification port
  808. hNetInterface - Supplies the network interface to be added
  809. dwFilter - Supplies the set of notification events to be added.
  810. dwNotifyKey - Supplies the notification key to be returned on
  811. any notification events for this network
  812. Return Value:
  813. ERROR_SUCCESS if successful
  814. Win32 error code otherwise.
  815. --*/
  816. {
  817. DWORD Status;
  818. PNOTIFY_PORT Port;
  819. PNM_INTERFACE NetInterface;
  820. DWORD NotifyFilter = 0;
  821. CLUSTER_NETINTERFACE_STATE CurrentState;
  822. API_ASSERT_INIT();
  823. VALIDATE_NOTIFY(Port, hNotify);
  824. VALIDATE_NETINTERFACE_EXISTS(NetInterface, hNetInterface);
  825. CurrentState = NmGetInterfaceState( NetInterface );
  826. ClRtlLogPrint(LOG_NOISE,
  827. "[API] s_ApiReAddNotifyNetInterface for %1!ws! (%2!lx!) oldstate %3!d! newstate %4!d!\n",
  828. OmObjectName(NetInterface),
  829. dwFilter,
  830. dwStateSequence,
  831. CurrentState);
  832. if ((DWORD)CurrentState != dwStateSequence) {
  833. NotifyFilter = CLUSTER_CHANGE_NETINTERFACE_STATE & dwFilter;
  834. } else {
  835. NotifyFilter = 0;
  836. }
  837. Status = ApipAddNotifyInterest(Port,
  838. (PAPI_HANDLE)hNetInterface,
  839. dwFilter,
  840. dwNotifyKey,
  841. NotifyFilter);
  842. return(Status);
  843. }
  844. error_status_t
  845. s_ApiReAddNotifyResource(
  846. IN HNOTIFY_RPC hNotify,
  847. IN HRES_RPC hResource,
  848. IN DWORD dwFilter,
  849. IN DWORD dwNotifyKey,
  850. IN DWORD dwStateSequence
  851. )
  852. /*++
  853. Routine Description:
  854. Adds a resource-specific notification event to an existing
  855. cluster notification port
  856. Arguments:
  857. hNotify - Supplies the notification port
  858. hResource - Supplies the resource to be added
  859. dwFilter - Supplies the set of notification events to be added.
  860. dwNotifyKey - Supplies the notification key to be returned on
  861. any notification events for this group
  862. Return Value:
  863. ERROR_SUCCESS if successful
  864. Win32 error code otherwise.
  865. --*/
  866. {
  867. DWORD Status;
  868. PNOTIFY_PORT Port;
  869. PFM_RESOURCE Resource;
  870. DWORD NotifyFilter;
  871. API_ASSERT_INIT();
  872. VALIDATE_NOTIFY(Port, hNotify);
  873. VALIDATE_RESOURCE_EXISTS(Resource, hResource);
  874. ClRtlLogPrint(LOG_NOISE,
  875. "[API] s_ApiReAddNotifyGroup for %1!ws! (%2!lx!) oldstate %3!d! newstate %4!d!\n",
  876. OmObjectName(Resource),
  877. dwFilter,
  878. dwStateSequence,
  879. Resource->StateSequence);
  880. if (Resource->StateSequence != dwStateSequence) {
  881. NotifyFilter = CLUSTER_CHANGE_RESOURCE_STATE & dwFilter;
  882. } else {
  883. NotifyFilter = 0;
  884. }
  885. Status = ApipAddNotifyInterest(Port,
  886. (PAPI_HANDLE)hResource,
  887. dwFilter,
  888. dwNotifyKey,
  889. NotifyFilter);
  890. return(Status);
  891. }
  892. error_status_t
  893. s_ApiAddNotifyKey(
  894. IN HNOTIFY_RPC hNotify,
  895. IN HKEY_RPC hKey,
  896. IN DWORD dwNotifyKey,
  897. IN DWORD Filter,
  898. IN BOOL WatchSubTree
  899. )
  900. /*++
  901. Routine Description:
  902. Adds a registry notification event to an existing
  903. cluster notification port
  904. Arguments:
  905. hNotify - Supplies the notification port
  906. hKey - Supplies the key to be added
  907. dwNotifyKey - Supplies the notification key to be returned on
  908. any notification events for this group
  909. WatchSubTree - Supplies whether the notification applies to just
  910. the specified key or to the keys entire subtree
  911. Return Value:
  912. ERROR_SUCCESS if successful
  913. Win32 error code otherwise.
  914. --*/
  915. {
  916. DWORD Status;
  917. PNOTIFY_PORT Port;
  918. HDMKEY Key;
  919. API_ASSERT_INIT();
  920. VALIDATE_NOTIFY(Port, hNotify);
  921. VALIDATE_KEY(Key, hKey);
  922. Status = DmNotifyChangeKey(Key,
  923. Filter,
  924. WatchSubTree,
  925. &Port->RegistryList,
  926. ApiReportRegistryNotify,
  927. (DWORD_PTR)Port,
  928. dwNotifyKey);
  929. return(Status);
  930. }
  931. void
  932. HNOTIFY_RPC_rundown(
  933. IN HNOTIFY_RPC hNotify
  934. )
  935. /*++
  936. Routine Description:
  937. RPC rundown routine for notification ports.
  938. Arguments:
  939. hNotify - Supplies the notification port to be rundown
  940. Return Value:
  941. None.
  942. --*/
  943. {
  944. s_ApiCloseNotify(&hNotify);
  945. }
  946. error_status_t
  947. s_ApiUnblockGetNotifyCall(
  948. IN HNOTIFY_RPC hNotify
  949. )
  950. /*++
  951. Routine Description:
  952. Unblocks the s_ApiGetNotify call.
  953. Arguments:
  954. hNotify - Supplies the notification port to be closed.
  955. Return Value:
  956. None.
  957. --*/
  958. {
  959. PNOTIFY_PORT pPort;
  960. //
  961. // Chittur Subbaraman (chitturs) - 4/19/2000
  962. //
  963. // In order to prevent the client from calling ApiGetNotify
  964. // during or after the context handle is destroyed, we split
  965. // the notification port close into two steps. In the first step,
  966. // we merely unblock the ApiGetNotify call without freeing the
  967. // context handle. That is the purpose of this function.
  968. // In the next step, we free the context handle. The client can now
  969. // perform the notification port close in 2 steps, properly
  970. // synchronizing the freeing of the context handle with the call to
  971. // ApiGetNotify. This avoids an AV in RPC code caused by the
  972. // ApiGetNotify call being made during or soon after the context
  973. // handle is freed.
  974. //
  975. API_ASSERT_INIT();
  976. VALIDATE_NOTIFY( pPort, hNotify );
  977. DELETE_HANDLE( hNotify );
  978. ApipUnblockGetNotifyCall( pPort );
  979. return( ERROR_SUCCESS );
  980. }
  981. DWORD
  982. s_ApiCloseNotify(
  983. IN OUT HNOTIFY_RPC *phNotify
  984. )
  985. /*++
  986. Routine Description:
  987. Closes a cluster notification port and unblocks the s_ApiGetNotify
  988. thread, if necessary.
  989. Arguments:
  990. phNotify - Supplies the pointer to the notification port to be closed.
  991. Returns NULL
  992. Return Value:
  993. ERROR_SUCCESS.
  994. --*/
  995. {
  996. PNOTIFY_PORT pPort;
  997. API_ASSERT_INIT();
  998. if ( !IS_HANDLE_DELETED( *phNotify ) )
  999. {
  1000. //
  1001. // If the handle is not already deleted, this means this call is
  1002. // coming from a client that does not make the ApiUnblockGetNotify
  1003. // call. In such a case, do all the work of unblocking the
  1004. // ApiGetNotify thread and freeing the context handle.
  1005. //
  1006. VALIDATE_NOTIFY( pPort, *phNotify );
  1007. ApipUnblockGetNotifyCall( pPort );
  1008. } else
  1009. {
  1010. pPort = ((PAPI_HANDLE)(*phNotify))->Notify;
  1011. }
  1012. DeleteCriticalSection(&pPort->Lock);
  1013. LocalFree( pPort );
  1014. LocalFree( *phNotify );
  1015. *phNotify = NULL;
  1016. return( ERROR_SUCCESS );
  1017. }
  1018. error_status_t
  1019. s_ApiGetNotify(
  1020. IN HNOTIFY_RPC hNotify,
  1021. IN DWORD Timeout,
  1022. OUT DWORD *dwNotifyKey,
  1023. OUT DWORD *dwFilter,
  1024. OUT DWORD *dwStateSequence,
  1025. OUT LPWSTR *Name
  1026. )
  1027. /*++
  1028. Routine Description:
  1029. Retrieves a cluster notification event from a notify port
  1030. Arguments:
  1031. hNotify - Supplies the notification port
  1032. Timeout - Supplies the time to wait in ms.
  1033. dwNotifyKey - Returns the notification key of the event
  1034. dwFilter - Returns the notification type of the event
  1035. dwStateSequence - Returns the current state sequence of the object.
  1036. Name - Returns the name of the event. This buffer must be
  1037. freed on the client side with MIDL_user_free
  1038. Return Value:
  1039. ERROR_SUCCESS if successful
  1040. Win32 error code otherwise
  1041. --*/
  1042. {
  1043. PNOTIFY_PORT Port;
  1044. PLIST_ENTRY ListEntry;
  1045. PITEM Item;
  1046. DWORD NameLen;
  1047. LPCWSTR ObjectName;
  1048. LPWSTR NullName = L"";
  1049. DWORD StateSequence = 0;
  1050. API_ASSERT_INIT();
  1051. VALIDATE_NOTIFY(Port, hNotify);
  1052. //
  1053. // Make sure that Port is valid.
  1054. //
  1055. if ( Port == NULL ) {
  1056. return(ERROR_INVALID_HANDLE);
  1057. }
  1058. //
  1059. // Wait for something to arrive in the queue.
  1060. // Take the lock to make sure the notify port doesn't
  1061. // disappear out from under us.
  1062. //
  1063. EnterCriticalSection(&Port->Lock);
  1064. if (IS_HANDLE_DELETED(hNotify)) {
  1065. ListEntry = NULL;
  1066. } else {
  1067. ListEntry = ClRtlRemoveHeadQueue(&Port->Queue);
  1068. }
  1069. LeaveCriticalSection(&Port->Lock);
  1070. if (ListEntry == NULL) {
  1071. return(ERROR_NO_MORE_ITEMS);
  1072. }
  1073. Item = CONTAINING_RECORD(ListEntry, ITEM, ListEntry);
  1074. if (Item->FilterType & ITEM_TYPE_OBJECT_NAME) {
  1075. ObjectName = OmObjectName( Item->Object );
  1076. } else if (Item->FilterType & ITEM_TYPE_OBJECT_ID) {
  1077. ObjectName = OmObjectId( Item->Object );
  1078. } else if (Item->FilterType & ITEM_TYPE_NAME) {
  1079. ObjectName = Item->KeyName;
  1080. } else {
  1081. ClRtlLogPrint(LOG_CRITICAL,
  1082. "[API] s_ApiGetNotify: Unrecognized filter type,0x%1!08lx!\r\n",
  1083. Item->FilterType);
  1084. LocalFree(Item);
  1085. #if DBG
  1086. CL_ASSERT(FALSE)
  1087. #endif
  1088. return(ERROR_INVALID_PARAMETER);
  1089. }
  1090. //
  1091. // Get the state sequence for those notifications that have
  1092. // state sequences.
  1093. //
  1094. if (Item->FilterType & CLUSTER_CHANGE_GROUP_STATE) {
  1095. StateSequence = ((PFM_GROUP)(Item->Object))->StateSequence;
  1096. } else if (Item->FilterType & CLUSTER_CHANGE_RESOURCE_STATE) {
  1097. StateSequence = ((PFM_RESOURCE)(Item->Object))->StateSequence;
  1098. } else if (Item->FilterType & CLUSTER_CHANGE_NODE_STATE) {
  1099. StateSequence = NmGetNodeState((PNM_NODE)(Item->Object));
  1100. }
  1101. if ( ObjectName == NULL ) {
  1102. ObjectName = NullName;
  1103. }
  1104. NameLen = (lstrlenW(ObjectName)+1)*sizeof(WCHAR);
  1105. *Name = MIDL_user_allocate(NameLen);
  1106. if (*Name != NULL) {
  1107. CopyMemory(*Name, ObjectName, NameLen);
  1108. }
  1109. *dwFilter = Item->FilterType;
  1110. *dwNotifyKey = Item->NotifyKey;
  1111. *dwStateSequence = StateSequence;
  1112. if (Item->FilterType & (ITEM_TYPE_OBJECT_NAME | ITEM_TYPE_OBJECT_ID)) {
  1113. OmDereferenceObject(Item->Object);
  1114. }
  1115. LocalFree(Item);
  1116. if (*Name == NULL) {
  1117. return(ERROR_NOT_ENOUGH_MEMORY);
  1118. } else {
  1119. return(ERROR_SUCCESS);
  1120. }
  1121. }
  1122. DWORD
  1123. ApipAddNotifyInterest(
  1124. IN PNOTIFY_PORT Notify,
  1125. IN PAPI_HANDLE ObjectHandle,
  1126. IN DWORD Filter,
  1127. IN DWORD NotifyKey,
  1128. IN DWORD NotifyFilter
  1129. )
  1130. /*++
  1131. Routine Description:
  1132. Registers a notification interest on an existing
  1133. cluster notification port
  1134. Arguments:
  1135. Notify - Supplies the notification port
  1136. ObjectHandle - Supplies a pointer to the object's handle.
  1137. Filter - Supplies the set of notification events to be added.
  1138. NotifyKey - Supplies the notification key to be returned on
  1139. any notification events
  1140. NotifyNow - Supplies whether a notification should be immediately
  1141. posted (TRUE).
  1142. NotifyFilter - If not zero, indicates that a notification should be
  1143. immediately posted with the specified filter.
  1144. Return Value:
  1145. ERROR_SUCCESS if successful
  1146. Win32 error code otherwise.
  1147. --*/
  1148. {
  1149. PINTEREST Interest;
  1150. PITEM Item;
  1151. if (Filter == 0) {
  1152. return(ERROR_SUCCESS);
  1153. }
  1154. Interest = LocalAlloc(LMEM_FIXED, sizeof(INTEREST));
  1155. if (Interest == NULL) {
  1156. return(ERROR_NOT_ENOUGH_MEMORY);
  1157. }
  1158. Interest->Object = ObjectHandle->Cluster;
  1159. Interest->Filter = Filter;
  1160. Interest->Key = NotifyKey;
  1161. EnterCriticalSection(&NotifyListLock);
  1162. InsertHeadList(&Notify->InterestList, &Interest->ListEntry);
  1163. InsertHeadList(&ObjectHandle->NotifyList, &Interest->HandleList);
  1164. Notify->Filter |= Filter;
  1165. if (NotifyFilter) {
  1166. //
  1167. // Post an immediate notification on this object.
  1168. //
  1169. //SS: this assert is wrong because you can have a filter
  1170. //that is a combination of say CLUSTER_CHANGE_GROUP_STATE+CLUSTER_CHANGE_HANDLE_CLOSE
  1171. //and that is perfectly valid
  1172. //CL_ASSERT(!(Filter & ITEM_TYPE_NAME));
  1173. Item = LocalAlloc(LMEM_FIXED, sizeof(ITEM));
  1174. if (Item != NULL) {
  1175. Item->FilterType = NotifyFilter;
  1176. Item->NotifyKey = Interest->Key;
  1177. Item->Object = ObjectHandle->Node;
  1178. OmReferenceObject(ObjectHandle->Node);
  1179. ClRtlInsertTailQueue(&Notify->Queue, &Item->ListEntry);
  1180. }
  1181. }
  1182. LeaveCriticalSection(&NotifyListLock);
  1183. return(ERROR_SUCCESS);
  1184. }
  1185. DWORD
  1186. ApipUnblockGetNotifyCall(
  1187. PNOTIFY_PORT pPort
  1188. )
  1189. /*++
  1190. Routine Description:
  1191. Unblocks the s_ApiGetNotify call.
  1192. Arguments:
  1193. pPort - Port associated with the session.
  1194. Return Value:
  1195. ERROR_SUCCESS.
  1196. --*/
  1197. {
  1198. PINTEREST Interest;
  1199. PLIST_ENTRY ListEntry;
  1200. LIST_ENTRY RundownList;
  1201. PITEM Item;
  1202. EnterCriticalSection(&NotifyListLock);
  1203. RemoveEntryList(&pPort->ListEntry);
  1204. //
  1205. // rundown registry notifications
  1206. //
  1207. DmRundownList(&pPort->RegistryList);
  1208. //
  1209. // Abort any waiters on the queue and rundown any
  1210. // items that may have already been posted to the
  1211. // queue.
  1212. //
  1213. ClRtlRundownQueue(&pPort->Queue, &RundownList);
  1214. while (!IsListEmpty(&RundownList)) {
  1215. ListEntry = RemoveHeadList(&RundownList);
  1216. Item = CONTAINING_RECORD(ListEntry,
  1217. ITEM,
  1218. ListEntry);
  1219. if (!(Item->FilterType & ITEM_TYPE_NAME)) {
  1220. OmDereferenceObject(Item->Object);
  1221. }
  1222. LocalFree(Item);
  1223. }
  1224. EnterCriticalSection(&pPort->Lock);
  1225. ClRtlDeleteQueue(&pPort->Queue);
  1226. LeaveCriticalSection(&pPort->Lock);
  1227. //
  1228. // rundown list of notify interests and delete each one.
  1229. //
  1230. while (!IsListEmpty(&pPort->InterestList)) {
  1231. ListEntry = RemoveHeadList(&pPort->InterestList);
  1232. Interest = CONTAINING_RECORD(ListEntry, INTEREST, ListEntry);
  1233. RemoveEntryList(&Interest->HandleList);
  1234. LocalFree(Interest);
  1235. }
  1236. LeaveCriticalSection(&NotifyListLock);
  1237. return(ERROR_SUCCESS);
  1238. }