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.

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