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.

1741 lines
37 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. clusnet.c
  5. Abstract:
  6. Intialization and dispatch routines for the Cluster Network Driver.
  7. Author:
  8. Mike Massa (mikemas) July 29, 1996
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. mikemas 07-29-96 created
  13. Notes:
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #include "clusnet.tmh"
  18. #include <sspi.h>
  19. //
  20. // Global Data
  21. //
  22. PDRIVER_OBJECT CnDriverObject = NULL;
  23. PDEVICE_OBJECT CnDeviceObject = NULL;
  24. KSPIN_LOCK CnDeviceObjectStackSizeLock = 0;
  25. PDEVICE_OBJECT CdpDeviceObject = NULL;
  26. PKPROCESS CnSystemProcess = NULL;
  27. CN_STATE CnState = CnStateShutdown;
  28. PERESOURCE CnResource = NULL;
  29. CL_NODE_ID CnMinValidNodeId = ClusterInvalidNodeId;
  30. CL_NODE_ID CnMaxValidNodeId = ClusterInvalidNodeId;
  31. CL_NODE_ID CnLocalNodeId = ClusterInvalidNodeId;
  32. KSPIN_LOCK CnShutdownLock = 0;
  33. BOOLEAN CnShutdownScheduled = FALSE;
  34. PKEVENT CnShutdownEvent = NULL;
  35. WORK_QUEUE_ITEM CnShutdownWorkItem = {{NULL, NULL}, NULL, NULL};
  36. HANDLE ClussvcProcessHandle = NULL;
  37. PSECURITY_DESCRIPTOR CdpAdminSecurityDescriptor = NULL;
  38. //
  39. // vars for managing Events. The lookaside list generates Event data structs
  40. // that are used to carry the data back to user mode. EventLock is the only
  41. // lock and synchronizes all access to any event structure (both here and in
  42. // CN_FSCONTEXT). EventFileHandles is a list of CN_FSCONTEXT structs that
  43. // are interested in receiving event notifications. To avoid synchronization
  44. // problems between clusnet and mm in clussvc, events have an epoch associated
  45. // with them. MM increments the epoch at the beginning of regroup event and
  46. // updates clusnet at the end of regroup. Any events still pending in the
  47. // event queue with a stale epoch are ignored by MM.
  48. //
  49. // EventDeliveryInProgress is a count of threads that are currently
  50. // iterating through the EventFileHandles list and delivering events.
  51. // The EventFileHandles list cannot be modified while EventDeliveryInProgress
  52. // is greater than zero. EventDeliveryComplete is a notification event
  53. // that is signalled when the EventDeliveryInProgress count reaches zero.
  54. // EventRevisitRequired indicates whether a new event IRP arrived during
  55. // event delivery. To avoid delivering events out of order, the IRP cannot
  56. // be completed immediately.
  57. //
  58. PNPAGED_LOOKASIDE_LIST EventLookasideList = NULL;
  59. LIST_ENTRY EventFileHandles = {0,0};
  60. #if DBG
  61. CN_LOCK EventLock = {0,0};
  62. #else
  63. CN_LOCK EventLock = 0;
  64. #endif
  65. ULONG EventEpoch;
  66. LONG EventDeliveryInProgress = 0;
  67. KEVENT EventDeliveryComplete;
  68. BOOLEAN EventRevisitRequired = FALSE;
  69. #if DBG
  70. ULONG CnDebug = 0;
  71. #endif // DBG
  72. //
  73. // Private Types
  74. //
  75. //
  76. // Private Data
  77. //
  78. SECURITY_STATUS
  79. SEC_ENTRY
  80. SecSetPagingMode(
  81. BOOLEAN Pageable
  82. );
  83. BOOLEAN SecurityPagingModeSet = FALSE;
  84. //
  85. // Local Prototypes
  86. //
  87. NTSTATUS
  88. DriverEntry(
  89. IN PDRIVER_OBJECT DriverObject,
  90. IN PUNICODE_STRING RegistryPath
  91. );
  92. VOID
  93. DriverUnload(
  94. IN PDRIVER_OBJECT DriverObject
  95. );
  96. NTSTATUS
  97. CnCreateDeviceObjects(
  98. IN PDRIVER_OBJECT DriverObject
  99. );
  100. VOID
  101. CnDeleteDeviceObjects(
  102. VOID
  103. );
  104. VOID
  105. CnAdjustDeviceObjectStackSize(
  106. PDEVICE_OBJECT ClusnetDeviceObject,
  107. PDEVICE_OBJECT TargetDeviceObject
  108. );
  109. NTSTATUS
  110. CnBuildDeviceAcl(
  111. OUT PACL *DeviceAcl
  112. );
  113. NTSTATUS
  114. CnCreateSecurityDescriptor(
  115. VOID
  116. );
  117. //
  118. // Mark init code as discardable.
  119. //
  120. #ifdef ALLOC_PRAGMA
  121. #pragma alloc_text(INIT, DriverEntry)
  122. #pragma alloc_text(INIT, CnCreateDeviceObjects)
  123. #pragma alloc_text(INIT, CnCreateSecurityDescriptor)
  124. #pragma alloc_text(INIT, CnBuildDeviceAcl)
  125. #pragma alloc_text(PAGE, DriverUnload)
  126. #pragma alloc_text(PAGE, CnDeleteDeviceObjects)
  127. #endif // ALLOC_PRAGMA
  128. //
  129. // Function definitions
  130. //
  131. NTSTATUS
  132. DriverEntry(
  133. IN PDRIVER_OBJECT DriverObject,
  134. IN PUNICODE_STRING RegistryPath
  135. )
  136. /*++
  137. Routine Description:
  138. Initialization routine for the driver.
  139. Arguments:
  140. DriverObject - Pointer to the driver object created by the system.
  141. RegistryPath - The driver's registry key.
  142. Return Value:
  143. An NT status code.
  144. --*/
  145. {
  146. NTSTATUS status;
  147. USHORT i;
  148. #if DBG
  149. volatile BOOLEAN DontLoad = FALSE;
  150. if ( DontLoad )
  151. return STATUS_UNSUCCESSFUL;
  152. #endif
  153. IF_CNDBG(CN_DEBUG_INIT) {
  154. CNPRINT(("[ClusNet] Loading...\n"));
  155. }
  156. WPP_INIT_TRACING(DriverObject, RegistryPath);
  157. //
  158. // Save a pointer to the system process so that we can open
  159. // handles in the context of this process later.
  160. //
  161. CnSystemProcess = (PKPROCESS) IoGetCurrentProcess();
  162. //
  163. // Allocate a synchronization resource.
  164. //
  165. CnResource = CnAllocatePool(sizeof(ERESOURCE));
  166. if (CnResource == NULL) {
  167. return(STATUS_INSUFFICIENT_RESOURCES);
  168. }
  169. status = ExInitializeResourceLite(CnResource);
  170. if (!NT_SUCCESS(status)) {
  171. goto error_exit;
  172. }
  173. //
  174. // initialize the mechanisms used to deliver event callbacks
  175. // to user mode
  176. //
  177. EventLookasideList = CnAllocatePool(sizeof(NPAGED_LOOKASIDE_LIST));
  178. if (EventLookasideList == NULL) {
  179. status = STATUS_INSUFFICIENT_RESOURCES;
  180. }
  181. ExInitializeNPagedLookasideList(EventLookasideList,
  182. NULL,
  183. NULL,
  184. 0,
  185. sizeof( CLUSNET_EVENT_ENTRY ),
  186. CN_EVENT_SIGNATURE,
  187. 0);
  188. CnInitializeLock( &EventLock, CNP_EVENT_LOCK );
  189. InitializeListHead( &EventFileHandles );
  190. KeInitializeEvent( &EventDeliveryComplete, NotificationEvent, TRUE );
  191. //
  192. // Initialize miscellaneous other items.
  193. //
  194. KeInitializeSpinLock(&CnShutdownLock);
  195. KeInitializeSpinLock(&CnDeviceObjectStackSizeLock);
  196. //
  197. // Initialize the driver object
  198. //
  199. CnDriverObject = DriverObject;
  200. DriverObject->DriverUnload = DriverUnload;
  201. DriverObject->FastIoDispatch = NULL;
  202. for (i=0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
  203. DriverObject->MajorFunction[i] = CnDispatch;
  204. }
  205. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
  206. CnDispatchDeviceControl;
  207. DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
  208. CnDispatchInternalDeviceControl;
  209. //
  210. // Create all the devices exported by this driver.
  211. //
  212. status = CnCreateDeviceObjects(DriverObject);
  213. if (!NT_SUCCESS(status)) {
  214. goto error_exit;
  215. }
  216. //
  217. // Initialize the CDP security descriptor.
  218. //
  219. status = CnCreateSecurityDescriptor();
  220. if (!NT_SUCCESS(status)) {
  221. goto error_exit;
  222. }
  223. #ifdef MEMLOGGING
  224. //
  225. // initialize the in-memory log
  226. //
  227. CnInitializeMemoryLog();
  228. #endif // MEMLOGGING
  229. //
  230. // Load the IP Address and NetBT support.
  231. // This must be done before the transport registers for PnP events.
  232. //
  233. status = IpaLoad();
  234. if (!NT_SUCCESS(status)) {
  235. goto error_exit;
  236. }
  237. status = NbtIfLoad();
  238. if (!NT_SUCCESS(status)) {
  239. goto error_exit;
  240. }
  241. //
  242. // Load the transport component
  243. //
  244. status = CxLoad(RegistryPath);
  245. if (!NT_SUCCESS(status)) {
  246. goto error_exit;
  247. }
  248. #ifdef MM_IN_CLUSNET
  249. //
  250. // Load the membership component
  251. //
  252. status = CmmLoad(RegistryPath);
  253. if (!NT_SUCCESS(status)) {
  254. goto error_exit;
  255. }
  256. #endif // MM_IN_CLUSNET
  257. //
  258. // make ksecdd non-pagable so we can sign and verify
  259. // signatures at raised IRQL
  260. //
  261. status = SecSetPagingMode( FALSE );
  262. if (!NT_SUCCESS(status)) {
  263. goto error_exit;
  264. }
  265. SecurityPagingModeSet = TRUE;
  266. IF_CNDBG(CN_DEBUG_INIT) {
  267. CNPRINT(("[ClusNet] Loaded.\n"));
  268. }
  269. return(STATUS_SUCCESS);
  270. error_exit:
  271. DriverUnload(CnDriverObject);
  272. return(status);
  273. }
  274. VOID
  275. DriverUnload(
  276. IN PDRIVER_OBJECT DriverObject
  277. )
  278. /*++
  279. Routine Description:
  280. Unloads the driver.
  281. Arguments:
  282. DriverObject - Pointer to the driver object created by the system.
  283. Return Value:
  284. None
  285. --*/
  286. {
  287. PAGED_CODE();
  288. IF_CNDBG(CN_DEBUG_INIT) {
  289. CNPRINT(("[ClusNet] Unloading...\n"));
  290. }
  291. CnTrace(HBEAT_ERROR,0, "[ClusNet] Unloading...\n");
  292. //
  293. // First, force a shutdown.
  294. //
  295. CnShutdown();
  296. //
  297. // Now unload the components.
  298. //
  299. #ifdef MM_IN_CLUSNET
  300. CmmUnload();
  301. #endif // MM_IN_CLUSNET
  302. CxUnload();
  303. #ifdef MEMLOGGING
  304. //
  305. // initialize the in-memory log
  306. //
  307. CnFreeMemoryLog();
  308. #endif // MEMLOGGING
  309. if (CdpAdminSecurityDescriptor != NULL) {
  310. ExFreePool(CdpAdminSecurityDescriptor);
  311. CdpAdminSecurityDescriptor = NULL;
  312. }
  313. CnDeleteDeviceObjects();
  314. if (CnResource != NULL) {
  315. ExDeleteResourceLite(CnResource);
  316. CnFreePool(CnResource); CnResource = NULL;
  317. }
  318. CnDriverObject = NULL;
  319. IF_CNDBG(CN_DEBUG_INIT) {
  320. CNPRINT(("[ClusNet] Unloaded.\n"));
  321. }
  322. if (EventLookasideList != NULL) {
  323. ExDeleteNPagedLookasideList( EventLookasideList );
  324. CnFreePool( EventLookasideList ); EventLookasideList = NULL;
  325. }
  326. //
  327. // finally, allow the security driver to return to nonpaged mode
  328. //
  329. if ( SecurityPagingModeSet ) {
  330. SecSetPagingMode( TRUE );
  331. }
  332. WPP_CLEANUP(DriverObject);
  333. return;
  334. } // DriverUnload
  335. NTSTATUS
  336. CnCreateDeviceObjects(
  337. IN PDRIVER_OBJECT DriverObject
  338. )
  339. /*++
  340. Routine Description:
  341. Creates the device objects exported by the driver.
  342. Arguments:
  343. DriverObject - Pointer to the driver object created by the system.
  344. Return Value:
  345. An NT status code.
  346. --*/
  347. {
  348. NTSTATUS status;
  349. UNICODE_STRING deviceName;
  350. //
  351. // Create the driver control device
  352. //
  353. RtlInitUnicodeString(&deviceName, DD_CLUSNET_DEVICE_NAME);
  354. status = IoCreateDevice(
  355. DriverObject,
  356. 0,
  357. &deviceName,
  358. FILE_DEVICE_NETWORK,
  359. 0,
  360. FALSE,
  361. &CnDeviceObject
  362. );
  363. if (!NT_SUCCESS(status)) {
  364. CNPRINT((
  365. "[ClusNet] Failed to create %ws device object, status %lx\n",
  366. deviceName.Buffer,
  367. status
  368. ));
  369. return(status);
  370. }
  371. CnDeviceObject->Flags |= DO_DIRECT_IO;
  372. CnDeviceObject->StackSize = CN_DEFAULT_IRP_STACK_SIZE;
  373. status = IoRegisterShutdownNotification(CnDeviceObject);
  374. if (!NT_SUCCESS(status)) {
  375. CNPRINT((
  376. "[ClusNet] Failed to register for shutdown notification, status %lx\n",
  377. status
  378. ));
  379. }
  380. #if defined(WMI_TRACING)
  381. status = IoWMIRegistrationControl (CnDeviceObject, WMIREG_ACTION_REGISTER);
  382. if (!NT_SUCCESS(status)) {
  383. CNPRINT(("[ClusNet] Failed to register for WMI Support, %lx\n", status) );
  384. }
  385. #endif
  386. //
  387. // Create the datagram transport device
  388. //
  389. RtlInitUnicodeString(&deviceName, DD_CDP_DEVICE_NAME);
  390. status = IoCreateDevice(
  391. DriverObject,
  392. 0,
  393. &deviceName,
  394. FILE_DEVICE_NETWORK,
  395. 0,
  396. FALSE,
  397. &CdpDeviceObject
  398. );
  399. if (!NT_SUCCESS(status)) {
  400. CNPRINT((
  401. "[ClusNet] Failed to create %ws device object, status %lx\n",
  402. deviceName.Buffer,
  403. status
  404. ));
  405. return(status);
  406. }
  407. CdpDeviceObject->Flags |= DO_DIRECT_IO;
  408. CdpDeviceObject->StackSize = CDP_DEFAULT_IRP_STACK_SIZE;
  409. return(STATUS_SUCCESS);
  410. }
  411. VOID
  412. CnDeleteDeviceObjects(
  413. VOID
  414. )
  415. /*++
  416. Routine Description:
  417. Deletes the device objects exported by the driver.
  418. Arguments:
  419. None.
  420. Return Value:
  421. None.
  422. --*/
  423. {
  424. PAGED_CODE();
  425. if (CnDeviceObject != NULL) {
  426. #if defined(WMI_TRACING)
  427. IoWMIRegistrationControl(CnDeviceObject, WMIREG_ACTION_DEREGISTER);
  428. #endif
  429. IoDeleteDevice(CnDeviceObject);
  430. CnDeviceObject = NULL;
  431. }
  432. if (CdpDeviceObject != NULL) {
  433. IoDeleteDevice(CdpDeviceObject);
  434. CdpDeviceObject = NULL;
  435. }
  436. return;
  437. }
  438. NTSTATUS
  439. CnInitialize(
  440. IN CL_NODE_ID LocalNodeId,
  441. IN ULONG MaxNodes
  442. )
  443. /*++
  444. Routine Description:
  445. Initialization routine for the Cluster Network Driver.
  446. Called when an initialize request is received.
  447. Arguments:
  448. LocalNodeId - The ID of the local node.
  449. MaxNodes - The maximum number of valid cluster nodes.
  450. Return Value:
  451. An NT status code.
  452. --*/
  453. {
  454. NTSTATUS status;
  455. if ( (MaxNodes == 0) ||
  456. (LocalNodeId < ClusterMinNodeId) ||
  457. (LocalNodeId > (ClusterMinNodeId + MaxNodes - 1))
  458. )
  459. {
  460. return(STATUS_INVALID_PARAMETER);
  461. }
  462. IF_CNDBG(CN_DEBUG_INIT) {
  463. CNPRINT(("[Clusnet] Initializing...\n"));
  464. }
  465. CnState = CnStateInitializePending;
  466. //
  467. // Reset global values
  468. //
  469. CnAssert(CnLocalNodeId == ClusterInvalidNodeId);
  470. CnAssert(CnMinValidNodeId == ClusterInvalidNodeId);
  471. CnAssert(CnMaxValidNodeId == ClusterInvalidNodeId);
  472. CnMinValidNodeId = ClusterMinNodeId;
  473. CnMaxValidNodeId = ClusterMinNodeId + MaxNodes - 1;
  474. CnLocalNodeId = LocalNodeId;
  475. //
  476. // Initialize the IP Address support
  477. //
  478. status = IpaInitialize();
  479. if (status != STATUS_SUCCESS) {
  480. goto error_exit;
  481. }
  482. #ifdef MM_IN_CLUSNET
  483. //
  484. // Call the Membership Manager's init routine. This will in turn call
  485. // the Transport's init routine.
  486. //
  487. status = CmmInitialize();
  488. #else // MM_IN_CLUSNET
  489. status = CxInitialize();
  490. #endif // MM_IN_CLUSNET
  491. if (status == STATUS_SUCCESS) {
  492. IF_CNDBG(CN_DEBUG_INIT) {
  493. CNPRINT(("[Clusnet] Initialized.\n"));
  494. }
  495. CnState = CnStateInitialized;
  496. }
  497. else {
  498. goto error_exit;
  499. }
  500. return(STATUS_SUCCESS);
  501. error_exit:
  502. IF_CNDBG(CN_DEBUG_INIT) {
  503. CNPRINT(("[Clusnet] Initialization failed, Shutting down. Status = %08X\n",
  504. status));
  505. }
  506. CnShutdown();
  507. return(status);
  508. } // CnInitialize
  509. NTSTATUS
  510. CnShutdown(
  511. VOID
  512. )
  513. /*++
  514. Routine Description:
  515. Terminates operation of the Cluster Membership Manager.
  516. Called when the Cluster Service is shutting down.
  517. Arguments:
  518. None.
  519. Return Value:
  520. None.
  521. --*/
  522. {
  523. NTSTATUS status;
  524. if ( (CnState == CnStateInitialized) ||
  525. (CnState == CnStateInitializePending)
  526. )
  527. {
  528. IF_CNDBG(CN_DEBUG_INIT) {
  529. CNPRINT(("[Clusnet] Shutting down...\n"));
  530. }
  531. CnState = CnStateShutdownPending;
  532. //
  533. // Shutdown the NetBT and IP Address support.
  534. //
  535. NbtIfShutdown();
  536. IpaShutdown();
  537. #ifdef MM_IN_CLUSNET
  538. //
  539. // Shutdown the Membership Manager. This will shutdown the
  540. // Transport as a side-effect.
  541. //
  542. CmmShutdown();
  543. #else // MM_IN_CLUSNET
  544. CxShutdown();
  545. #endif // MM_IN_CLUSNET
  546. IF_CNDBG(CN_DEBUG_INIT) {
  547. CNPRINT(("[Clusnet] Shutdown complete.\n"));
  548. }
  549. CnAssert(CnLocalNodeId != ClusterInvalidNodeId);
  550. CnMinValidNodeId = ClusterInvalidNodeId;
  551. CnMaxValidNodeId = ClusterInvalidNodeId;
  552. CnLocalNodeId = ClusterInvalidNodeId;
  553. CnState = CnStateShutdown;
  554. status = STATUS_SUCCESS;
  555. }
  556. else {
  557. status = STATUS_DEVICE_NOT_READY;
  558. }
  559. //
  560. // always test if we have a handle to this process
  561. // and remove it
  562. //
  563. if ( ClussvcProcessHandle ) {
  564. CnCloseProcessHandle( ClussvcProcessHandle );
  565. ClussvcProcessHandle = NULL;
  566. }
  567. return(status);
  568. } // CnShutdown
  569. VOID
  570. CnShutdownWorkRoutine(
  571. IN PVOID WorkItem
  572. )
  573. {
  574. BOOLEAN acquired;
  575. NTSTATUS Status;
  576. acquired = CnAcquireResourceExclusive(CnResource, TRUE);
  577. if (!acquired) {
  578. KIRQL irql;
  579. CNPRINT(("[Clusnet] Failed to acquire CnResource\n"));
  580. KeAcquireSpinLock(&CnShutdownLock, &irql);
  581. CnShutdownScheduled = FALSE;
  582. if (CnShutdownEvent != NULL) {
  583. KeSetEvent(CnShutdownEvent, IO_NO_INCREMENT, FALSE);
  584. }
  585. KeReleaseSpinLock(&CnShutdownLock, irql);
  586. return;
  587. }
  588. (VOID) CnShutdown();
  589. if (CnShutdownEvent != NULL) {
  590. KeSetEvent(CnShutdownEvent, IO_NO_INCREMENT, FALSE);
  591. }
  592. if (acquired) {
  593. CnReleaseResourceForThread(
  594. CnResource,
  595. (ERESOURCE_THREAD) PsGetCurrentThread()
  596. );
  597. }
  598. //
  599. // Leave CnShutdownScheduled = TRUE until we are reinitialized to
  600. // prevent scheduling unnecessary work items.
  601. //
  602. return;
  603. } // CnShutdownWorkRoutine
  604. BOOLEAN
  605. CnHaltOperation(
  606. IN PKEVENT ShutdownEvent OPTIONAL
  607. )
  608. /*++
  609. Routine Description:
  610. Schedules a critical worker thread to perform clusnet shutdown,
  611. if a thread is not already scheduled.
  612. Arguments:
  613. ShutdownEvent - if provided, event to be signalled after
  614. shutdown is complete
  615. Return value:
  616. TRUE if shutdown was scheduled. FALSE if shutdown was already
  617. scheduled (in which case ShutdownEvent will not be signalled).
  618. --*/
  619. {
  620. KIRQL irql;
  621. // Disable further processing of Clussvc to Clusnet Hbs.
  622. ClussvcClusnetHbTimeoutAction = ClussvcHangActionDisable;
  623. InterlockedExchange(&ClussvcClusnetHbTickCount, 0);
  624. ClussvcClusnetHbTimeoutTicks = 0;
  625. KeAcquireSpinLock(&CnShutdownLock, &irql);
  626. if (CnShutdownScheduled) {
  627. KeReleaseSpinLock(&CnShutdownLock, irql);
  628. return(FALSE);
  629. }
  630. CnShutdownScheduled = TRUE;
  631. CnShutdownEvent = ShutdownEvent;
  632. KeReleaseSpinLock(&CnShutdownLock, irql);
  633. //
  634. // Schedule a critical worker thread to do the shutdown work.
  635. //
  636. ExInitializeWorkItem(
  637. &CnShutdownWorkItem,
  638. CnShutdownWorkRoutine,
  639. &CnShutdownWorkItem
  640. );
  641. ExQueueWorkItem(&CnShutdownWorkItem, CriticalWorkQueue);
  642. return(TRUE);
  643. } // CnHaltOperation
  644. //
  645. // ExResource wrappers that disable APCs.
  646. //
  647. BOOLEAN
  648. CnAcquireResourceExclusive(
  649. IN PERESOURCE Resource,
  650. IN BOOLEAN Wait
  651. )
  652. {
  653. BOOLEAN acquired;
  654. KeEnterCriticalRegion();
  655. acquired = ExAcquireResourceExclusiveLite(Resource, Wait);
  656. if (!acquired) {
  657. KeLeaveCriticalRegion();
  658. }
  659. return(acquired);
  660. } // CnAcquireResourceExclusive
  661. BOOLEAN
  662. CnAcquireResourceShared(
  663. IN PERESOURCE Resource,
  664. IN BOOLEAN Wait
  665. )
  666. {
  667. BOOLEAN acquired;
  668. KeEnterCriticalRegion();
  669. acquired = ExAcquireResourceSharedLite(Resource, Wait);
  670. if (!acquired) {
  671. KeLeaveCriticalRegion();
  672. }
  673. return(acquired);
  674. } // CnAcquireResourceShared
  675. VOID
  676. CnReleaseResourceForThread(
  677. IN PERESOURCE Resource,
  678. IN ERESOURCE_THREAD ResourceThreadId
  679. )
  680. {
  681. ExReleaseResourceForThreadLite(Resource, ResourceThreadId);
  682. KeLeaveCriticalRegion();
  683. return;
  684. } // CnReleaseResourceForThread
  685. NTSTATUS
  686. CnCloseProcessHandle(
  687. HANDLE Handle
  688. )
  689. /*++
  690. Routine Description:
  691. Close the cluster service process handle
  692. Arguments:
  693. None
  694. Return Value:
  695. None
  696. --*/
  697. {
  698. NTSTATUS Status = STATUS_SUCCESS;
  699. CnAssert( Handle != NULL );
  700. KeAttachProcess( CnSystemProcess );
  701. Status = ZwClose( Handle );
  702. KeDetachProcess();
  703. IF_CNDBG(CN_DEBUG_INIT) {
  704. CNPRINT(("[Clusnet] Process handle released. status = %08X\n", Status));
  705. }
  706. return Status;
  707. }
  708. VOID
  709. CnEnableHaltProcessing(
  710. VOID
  711. )
  712. /*++
  713. Routine Description:
  714. Initializes global data for halt processing.
  715. Arguments:
  716. None
  717. Return Value:
  718. None
  719. --*/
  720. {
  721. KIRQL irql;
  722. KeAcquireSpinLock(&CnShutdownLock, &irql);
  723. CnShutdownScheduled = FALSE;
  724. CnShutdownEvent = NULL;
  725. KeReleaseSpinLock(&CnShutdownLock, irql);
  726. return;
  727. } // CnEnableHaltProcessing
  728. VOID
  729. CnAdjustDeviceObjectStackSize(
  730. PDEVICE_OBJECT ClusnetDeviceObject,
  731. PDEVICE_OBJECT TargetDeviceObject
  732. )
  733. /*++
  734. Routine Description
  735. Adjust the StackSize of ClusnetDeviceObject so that we
  736. can pass client IRPs down to TargetDeviceObject.
  737. The StackSize of clusnet device objects is initialized to
  738. a default that allows for some leeway for attached drivers.
  739. Arguments
  740. ClusnetDeviceObject - clusnet device object whose StackSize
  741. should be adjusted
  742. TargetDeviceObject - device object clusnet IRPs, originally
  743. issued to clusnet, will be forwarded to
  744. Return value
  745. None
  746. --*/
  747. {
  748. CCHAR defaultStackSize, newStackSize = 0;
  749. KIRQL irql;
  750. if (ClusnetDeviceObject == CnDeviceObject) {
  751. defaultStackSize = CN_DEFAULT_IRP_STACK_SIZE;
  752. }
  753. else if (ClusnetDeviceObject == CdpDeviceObject) {
  754. defaultStackSize = CDP_DEFAULT_IRP_STACK_SIZE;
  755. }
  756. else {
  757. IF_CNDBG(CN_DEBUG_INIT) {
  758. CNPRINT(("[Clusnet] CnAdjustDeviceObjectStackSize: "
  759. "unknown clusnet device object %p.\n",
  760. ClusnetDeviceObject
  761. ));
  762. }
  763. return;
  764. }
  765. KeAcquireSpinLock(&CnDeviceObjectStackSizeLock, &irql);
  766. if (ClusnetDeviceObject->StackSize <
  767. TargetDeviceObject->StackSize + defaultStackSize) {
  768. ClusnetDeviceObject->StackSize =
  769. TargetDeviceObject->StackSize + defaultStackSize;
  770. IF_CNDBG(CN_DEBUG_INIT) {
  771. newStackSize = ClusnetDeviceObject->StackSize;
  772. }
  773. }
  774. KeReleaseSpinLock(&CnDeviceObjectStackSizeLock, irql);
  775. IF_CNDBG(CN_DEBUG_INIT) {
  776. if (newStackSize != 0) {
  777. CNPRINT(("[Clusnet] Set StackSize of clusnet device "
  778. "object %p to %d "
  779. "based on target device object %p.\n",
  780. ClusnetDeviceObject,
  781. newStackSize,
  782. TargetDeviceObject
  783. ));
  784. }
  785. }
  786. return;
  787. } // CnAdjustDeviceObjectStackSize
  788. NTSTATUS
  789. CnBuildDeviceAcl(
  790. OUT PACL *DeviceAcl
  791. )
  792. /*++
  793. Routine Description:
  794. This routine builds an ACL which gives Administrators,
  795. LocalSystem, and NetworkService principals full access.
  796. All other principals have no access.
  797. Arguments:
  798. DeviceAcl - Output pointer to the new ACL.
  799. Return Value:
  800. STATUS_SUCCESS or an appropriate error code.
  801. Notes:
  802. This code was lifted from AFD.
  803. --*/
  804. {
  805. PGENERIC_MAPPING genericMapping;
  806. ULONG aclLength;
  807. NTSTATUS status;
  808. ACCESS_MASK accessMask = GENERIC_ALL;
  809. PACL newAcl;
  810. PAGED_CODE();
  811. //
  812. // Enable access to all the globally defined SIDs
  813. //
  814. genericMapping = IoGetFileObjectGenericMapping();
  815. RtlMapGenericMask( &accessMask, genericMapping );
  816. aclLength = sizeof( ACL ) +
  817. 3 * FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
  818. RtlLengthSid( SeExports->SeAliasAdminsSid ) +
  819. RtlLengthSid( SeExports->SeLocalSystemSid ) +
  820. RtlLengthSid( SeExports->SeNetworkServiceSid );
  821. newAcl = ExAllocatePoolWithTag(
  822. PagedPool,
  823. aclLength,
  824. CN_POOL_TAG
  825. );
  826. if (newAcl == NULL) {
  827. return (STATUS_INSUFFICIENT_RESOURCES);
  828. }
  829. status = RtlCreateAcl (newAcl, aclLength, ACL_REVISION );
  830. if (!NT_SUCCESS(status)) {
  831. ExFreePoolWithTag(
  832. newAcl,
  833. CN_POOL_TAG
  834. );
  835. return (status);
  836. }
  837. status = RtlAddAccessAllowedAce (
  838. newAcl,
  839. ACL_REVISION2,
  840. accessMask,
  841. SeExports->SeAliasAdminsSid
  842. );
  843. CnAssert(NT_SUCCESS(status));
  844. if (!NT_SUCCESS(status)) {
  845. CNPRINT((
  846. "[ClusNet] Failed to add Admin to ACL, error: %lx\n",
  847. status
  848. ));
  849. return(status);
  850. }
  851. status = RtlAddAccessAllowedAce (
  852. newAcl,
  853. ACL_REVISION2,
  854. accessMask,
  855. SeExports->SeLocalSystemSid
  856. );
  857. CnAssert(NT_SUCCESS(status));
  858. if (!NT_SUCCESS(status)) {
  859. CNPRINT((
  860. "[ClusNet] Failed to add LocalSystem to ACL, error: %lx\n",
  861. status
  862. ));
  863. return(status);
  864. }
  865. status = RtlAddAccessAllowedAce (
  866. newAcl,
  867. ACL_REVISION2,
  868. accessMask,
  869. SeExports->SeNetworkServiceSid
  870. );
  871. CnAssert(NT_SUCCESS(status));
  872. if (!NT_SUCCESS(status)) {
  873. CNPRINT((
  874. "[ClusNet] Failed to add NetworkService to ACL, error: %lx. "
  875. "(Non-fatal error)\n",
  876. status
  877. ));
  878. }
  879. *DeviceAcl = newAcl;
  880. return (STATUS_SUCCESS);
  881. } // CnBuildDeviceAcl
  882. NTSTATUS
  883. CnCreateSecurityDescriptor(
  884. VOID
  885. )
  886. /*++
  887. Routine Description:
  888. This routine creates a security descriptor which gives access
  889. only to certain priviliged accounts. This descriptor is used
  890. to access check CDP socket opens.
  891. Arguments:
  892. None.
  893. Return Value:
  894. STATUS_SUCCESS or an appropriate error code.
  895. Notes:
  896. This code was lifted from AFD.
  897. --*/
  898. {
  899. PACL devAcl = NULL;
  900. NTSTATUS status;
  901. BOOLEAN memoryAllocated = FALSE;
  902. PSECURITY_DESCRIPTOR cdpSecurityDescriptor;
  903. ULONG cdpSecurityDescriptorLength;
  904. CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
  905. PSECURITY_DESCRIPTOR localSecurityDescriptor =
  906. (PSECURITY_DESCRIPTOR)buffer;
  907. PSECURITY_DESCRIPTOR localCdpAdminSecurityDescriptor;
  908. SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION;
  909. PAGED_CODE();
  910. //
  911. // Get a pointer to the security descriptor from the CDP device object.
  912. //
  913. status = ObGetObjectSecurity(
  914. CdpDeviceObject,
  915. &cdpSecurityDescriptor,
  916. &memoryAllocated
  917. );
  918. if (!NT_SUCCESS(status)) {
  919. CNPRINT((
  920. "[ClusNet] Failed to get CDP device object security descriptor, "
  921. "status %lx\n",
  922. status
  923. ));
  924. return(status);
  925. }
  926. //
  927. // Build a local security descriptor with an ACL giving only
  928. // certain priviliged accounts.
  929. //
  930. status = CnBuildDeviceAcl(&devAcl);
  931. if (!NT_SUCCESS(status)) {
  932. CNPRINT((
  933. "[ClusNet] Failed to create Raw ACL, error: %lx\n",
  934. status
  935. ));
  936. goto error_exit;
  937. }
  938. (VOID) RtlCreateSecurityDescriptor(
  939. localSecurityDescriptor,
  940. SECURITY_DESCRIPTOR_REVISION
  941. );
  942. (VOID) RtlSetDaclSecurityDescriptor(
  943. localSecurityDescriptor,
  944. TRUE,
  945. devAcl,
  946. FALSE
  947. );
  948. //
  949. // Make a copy of the CDP descriptor. This copy will be
  950. // the raw descriptor.
  951. //
  952. cdpSecurityDescriptorLength = RtlLengthSecurityDescriptor(
  953. cdpSecurityDescriptor
  954. );
  955. localCdpAdminSecurityDescriptor = ExAllocatePoolWithTag (
  956. PagedPool,
  957. cdpSecurityDescriptorLength,
  958. CN_POOL_TAG
  959. );
  960. if (localCdpAdminSecurityDescriptor == NULL) {
  961. CNPRINT((
  962. "[ClusNet]: failed to allocate security descriptor "
  963. "of size %d.\n",
  964. cdpSecurityDescriptorLength
  965. ));
  966. status = STATUS_INSUFFICIENT_RESOURCES;
  967. goto error_exit;
  968. }
  969. RtlMoveMemory(
  970. localCdpAdminSecurityDescriptor,
  971. cdpSecurityDescriptor,
  972. cdpSecurityDescriptorLength
  973. );
  974. CdpAdminSecurityDescriptor = localCdpAdminSecurityDescriptor;
  975. //
  976. // Now apply the local descriptor to the raw descriptor.
  977. //
  978. status = SeSetSecurityDescriptorInfo(
  979. NULL,
  980. &securityInformation,
  981. localSecurityDescriptor,
  982. &CdpAdminSecurityDescriptor,
  983. PagedPool,
  984. IoGetFileObjectGenericMapping()
  985. );
  986. if (!NT_SUCCESS(status)) {
  987. CNPRINT((
  988. "[ClusNet]: SeSetSecurity failed for CDP admin "
  989. "security descriptor, %lx\n",
  990. status
  991. ));
  992. CnAssert(CdpAdminSecurityDescriptor == localCdpAdminSecurityDescriptor);
  993. ExFreePool(CdpAdminSecurityDescriptor);
  994. CdpAdminSecurityDescriptor = NULL;
  995. goto error_exit;
  996. }
  997. if (CdpAdminSecurityDescriptor != localCdpAdminSecurityDescriptor) {
  998. ExFreePool(localCdpAdminSecurityDescriptor);
  999. }
  1000. status = STATUS_SUCCESS;
  1001. error_exit:
  1002. ObReleaseObjectSecurity(
  1003. cdpSecurityDescriptor,
  1004. memoryAllocated
  1005. );
  1006. if (devAcl != NULL) {
  1007. ExFreePoolWithTag(
  1008. devAcl,
  1009. CN_POOL_TAG
  1010. );
  1011. }
  1012. return(status);
  1013. } // CnCreateSecurityDescriptor
  1014. #if DBG
  1015. //
  1016. // Debug code.
  1017. //
  1018. ULONG CnCpuLockMask[MAXIMUM_PROCESSORS];
  1019. VOID
  1020. CnAssertBreak(
  1021. PCHAR FailedStatement,
  1022. PCHAR FileName,
  1023. ULONG LineNumber
  1024. )
  1025. {
  1026. DbgPrint(
  1027. "[Clusnet] Assertion \"%s\" failed in %s line %u\n",
  1028. FailedStatement,
  1029. FileName,
  1030. LineNumber
  1031. );
  1032. DbgBreakPoint();
  1033. return;
  1034. } // CnAssertBreak
  1035. ULONG
  1036. CnGetCpuLockMask(
  1037. VOID
  1038. )
  1039. {
  1040. ULONG mask;
  1041. if (KeGetCurrentIrql() != DISPATCH_LEVEL) {
  1042. CnAssert(CnCpuLockMask[KeGetCurrentProcessorNumber()] == 0);
  1043. mask = 0;
  1044. }
  1045. else {
  1046. mask = CnCpuLockMask[KeGetCurrentProcessorNumber()];
  1047. }
  1048. return(mask);
  1049. }
  1050. VOID
  1051. CnVerifyCpuLockMask(
  1052. IN ULONG RequiredLockMask,
  1053. IN ULONG ForbiddenLockMask,
  1054. IN ULONG MaximumLockMask
  1055. )
  1056. {
  1057. ULONG mask;
  1058. if (KeGetCurrentIrql() < DISPATCH_LEVEL) {
  1059. mask = 0;
  1060. }
  1061. else {
  1062. mask = CnCpuLockMask[KeGetCurrentProcessorNumber()];
  1063. }
  1064. if ((mask & RequiredLockMask) != RequiredLockMask) {
  1065. CNPRINT((
  1066. "[Clusnet] Locking bug: Req'd lock mask %lx, actual mask %lx\n",
  1067. RequiredLockMask,
  1068. mask
  1069. ));
  1070. DbgBreakPoint();
  1071. }
  1072. if (mask & ForbiddenLockMask) {
  1073. CNPRINT((
  1074. "[Clusnet] Locking bug: Forbidden mask %lx, actual mask %lx\n",
  1075. ForbiddenLockMask,
  1076. mask
  1077. ));
  1078. DbgBreakPoint();
  1079. }
  1080. if (mask > MaximumLockMask) {
  1081. CNPRINT((
  1082. "[Clusnet] Locking bug: Max lock mask %lx, actual mask %lx\n",
  1083. MaximumLockMask,
  1084. mask
  1085. ));
  1086. DbgBreakPoint();
  1087. }
  1088. return;
  1089. }
  1090. VOID
  1091. CnInitializeLock(
  1092. PCN_LOCK Lock,
  1093. ULONG Rank
  1094. )
  1095. {
  1096. KeInitializeSpinLock(&(Lock->SpinLock));
  1097. Lock->Rank = Rank;
  1098. return;
  1099. }
  1100. VOID
  1101. CnAcquireLock(
  1102. IN PCN_LOCK Lock,
  1103. OUT PCN_IRQL Irql
  1104. )
  1105. {
  1106. KIRQL irql;
  1107. ULONG currentCpu;
  1108. if (KeGetCurrentIrql() != DISPATCH_LEVEL) {
  1109. KeRaiseIrql(DISPATCH_LEVEL, &irql);
  1110. }
  1111. else {
  1112. irql = DISPATCH_LEVEL;
  1113. }
  1114. currentCpu = KeGetCurrentProcessorNumber();
  1115. if (CnCpuLockMask[currentCpu] >= Lock->Rank) {
  1116. CNPRINT((
  1117. "[Clusnet] CPU %u trying to acquire lock %lx out of order, mask %lx\n",
  1118. currentCpu,
  1119. Lock->Rank,
  1120. CnCpuLockMask[currentCpu]
  1121. ));
  1122. DbgBreakPoint();
  1123. }
  1124. KeAcquireSpinLockAtDpcLevel(&(Lock->SpinLock));
  1125. *Irql = irql;
  1126. CnCpuLockMask[currentCpu] |= Lock->Rank;
  1127. return;
  1128. }
  1129. VOID
  1130. CnAcquireLockAtDpc(
  1131. IN PCN_LOCK Lock
  1132. )
  1133. {
  1134. ULONG currentCpu = KeGetCurrentProcessorNumber();
  1135. if (KeGetCurrentIrql() != DISPATCH_LEVEL) {
  1136. CNPRINT((
  1137. "[Clusnet] CPU %u trying to acquire DPC lock at passive level.\n",
  1138. currentCpu
  1139. ));
  1140. DbgBreakPoint();
  1141. }
  1142. if (CnCpuLockMask[currentCpu] >= Lock->Rank) {
  1143. CNPRINT((
  1144. "[Clusnet] CPU %u trying to acquire lock %lx out of order, mask %lx\n",
  1145. currentCpu,
  1146. Lock->Rank,
  1147. CnCpuLockMask[currentCpu]
  1148. ));
  1149. DbgBreakPoint();
  1150. }
  1151. KeAcquireSpinLockAtDpcLevel(&(Lock->SpinLock));
  1152. CnCpuLockMask[currentCpu] |= Lock->Rank;
  1153. return;
  1154. }
  1155. VOID
  1156. CnReleaseLock(
  1157. IN PCN_LOCK Lock,
  1158. IN CN_IRQL Irql
  1159. )
  1160. {
  1161. ULONG currentCpu = KeGetCurrentProcessorNumber();
  1162. if (KeGetCurrentIrql() != DISPATCH_LEVEL) {
  1163. CNPRINT((
  1164. "[Clusnet] CPU %u trying to release lock from passive level.\n",
  1165. currentCpu
  1166. ));
  1167. DbgBreakPoint();
  1168. }
  1169. if ( !(CnCpuLockMask[currentCpu] & Lock->Rank) ) {
  1170. CNPRINT((
  1171. "[Clusnet] CPU %u trying to release lock %lx, which it doesn't hold, mask %lx\n",
  1172. currentCpu,
  1173. Lock->Rank,
  1174. CnCpuLockMask[currentCpu]
  1175. ));
  1176. DbgBreakPoint();
  1177. }
  1178. CnCpuLockMask[currentCpu] &= ~(Lock->Rank);
  1179. KeReleaseSpinLock(&(Lock->SpinLock), Irql);
  1180. return;
  1181. }
  1182. VOID
  1183. CnReleaseLockFromDpc(
  1184. IN PCN_LOCK Lock
  1185. )
  1186. {
  1187. ULONG currentCpu = KeGetCurrentProcessorNumber();
  1188. if (KeGetCurrentIrql() != DISPATCH_LEVEL) {
  1189. CNPRINT((
  1190. "[Clusnet] CPU %u trying to release lock from passive level.\n",
  1191. currentCpu
  1192. ));
  1193. DbgBreakPoint();
  1194. }
  1195. if ( !(CnCpuLockMask[currentCpu] & Lock->Rank) ) {
  1196. CNPRINT((
  1197. "[Clusnet] CPU %u trying to release lock %lx, which it doesn't hold, mask %lx\n",
  1198. currentCpu,
  1199. Lock->Rank,
  1200. CnCpuLockMask[currentCpu]
  1201. ));
  1202. DbgBreakPoint();
  1203. }
  1204. CnCpuLockMask[currentCpu] &= ~(Lock->Rank);
  1205. KeReleaseSpinLockFromDpcLevel(&(Lock->SpinLock));
  1206. return;
  1207. }
  1208. VOID
  1209. CnMarkIoCancelLockAcquired(
  1210. VOID
  1211. )
  1212. {
  1213. ULONG currentCpu = KeGetCurrentProcessorNumber();
  1214. CnAssert(KeGetCurrentIrql() == DISPATCH_LEVEL);
  1215. CnAssert(!(CnCpuLockMask[currentCpu] & CN_IOCANCEL_LOCK));
  1216. CnAssert(CnCpuLockMask[currentCpu] < CN_IOCANCEL_LOCK_MAX);
  1217. CnCpuLockMask[currentCpu] |= CN_IOCANCEL_LOCK;
  1218. return;
  1219. }
  1220. VOID
  1221. CnAcquireCancelSpinLock(
  1222. OUT PCN_IRQL Irql
  1223. )
  1224. {
  1225. KIRQL irql;
  1226. KIRQL tempIrql;
  1227. ULONG currentCpu;
  1228. if (KeGetCurrentIrql() != DISPATCH_LEVEL) {
  1229. KeRaiseIrql(DISPATCH_LEVEL, &irql);
  1230. }
  1231. else {
  1232. irql = DISPATCH_LEVEL;
  1233. }
  1234. currentCpu = KeGetCurrentProcessorNumber();
  1235. if (CnCpuLockMask[currentCpu] >= CN_IOCANCEL_LOCK) {
  1236. CNPRINT((
  1237. "[Clusnet] CPU %u trying to acquire IoCancel lock out of order, mask %lx\n",
  1238. currentCpu,
  1239. CnCpuLockMask[currentCpu]
  1240. ));
  1241. DbgBreakPoint();
  1242. }
  1243. IoAcquireCancelSpinLock(&tempIrql);
  1244. CnAssert(tempIrql == DISPATCH_LEVEL);
  1245. *Irql = irql;
  1246. CnCpuLockMask[currentCpu] |= CN_IOCANCEL_LOCK;
  1247. return;
  1248. }
  1249. VOID
  1250. CnReleaseCancelSpinLock(
  1251. IN CN_IRQL Irql
  1252. )
  1253. {
  1254. ULONG currentCpu = KeGetCurrentProcessorNumber();
  1255. if (KeGetCurrentIrql() != DISPATCH_LEVEL) {
  1256. CNPRINT((
  1257. "[Clusnet] CPU %u trying to release lock from passive level.\n",
  1258. currentCpu
  1259. ));
  1260. DbgBreakPoint();
  1261. }
  1262. if ( !(CnCpuLockMask[currentCpu] & CN_IOCANCEL_LOCK) ) {
  1263. CNPRINT((
  1264. "[Clusnet] CPU %u trying to release IoCancel lock, which it doesn't hold, mask %lx\n",
  1265. currentCpu,
  1266. CnCpuLockMask[currentCpu]
  1267. ));
  1268. DbgBreakPoint();
  1269. }
  1270. CnCpuLockMask[currentCpu] &= ~(CN_IOCANCEL_LOCK);
  1271. IoReleaseCancelSpinLock(Irql);
  1272. return;
  1273. }
  1274. #endif // DEBUG