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.

1387 lines
27 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. //
  38. // vars for managing Events. The lookaside list generates Event data structs
  39. // that are used to carry the data back to user mode. EventLock is the only
  40. // lock and synchronizes all access to any event structure (both here and in
  41. // CN_FSCONTEXT). EventFileHandles is a list of CN_FSCONTEXT structs that
  42. // are interested in receiving event notifications. To avoid synchronization
  43. // problems between clusnet and mm in clussvc, events have an epoch associated
  44. // with them. MM increments the epoch at the beginning of regroup event and
  45. // updates clusnet at the end of regroup. Any events still pending in the
  46. // event queue with a stale epoch are ignored by MM.
  47. //
  48. // EventDeliveryInProgress is a count of threads that are currently
  49. // iterating through the EventFileHandles list and delivering events.
  50. // The EventFileHandles list cannot be modified while EventDeliveryInProgress
  51. // is greater than zero. EventDeliveryComplete is a notification event
  52. // that is signalled when the EventDeliveryInProgress count reaches zero.
  53. // EventRevisitRequired indicates whether a new event IRP arrived during
  54. // event delivery. To avoid delivering events out of order, the IRP cannot
  55. // be completed immediately.
  56. //
  57. PNPAGED_LOOKASIDE_LIST EventLookasideList = NULL;
  58. LIST_ENTRY EventFileHandles = {0,0};
  59. #if DBG
  60. CN_LOCK EventLock = {0,0};
  61. #else
  62. CN_LOCK EventLock = 0;
  63. #endif
  64. ULONG EventEpoch;
  65. LONG EventDeliveryInProgress = 0;
  66. KEVENT EventDeliveryComplete;
  67. BOOLEAN EventRevisitRequired = FALSE;
  68. #if DBG
  69. ULONG CnDebug = 0;
  70. #endif // DBG
  71. //
  72. // Private Types
  73. //
  74. //
  75. // Private Data
  76. //
  77. SECURITY_STATUS
  78. SEC_ENTRY
  79. SecSetPagingMode(
  80. BOOLEAN Pageable
  81. );
  82. BOOLEAN SecurityPagingModeSet = FALSE;
  83. //
  84. // Local Prototypes
  85. //
  86. NTSTATUS
  87. DriverEntry(
  88. IN PDRIVER_OBJECT DriverObject,
  89. IN PUNICODE_STRING RegistryPath
  90. );
  91. VOID
  92. DriverUnload(
  93. IN PDRIVER_OBJECT DriverObject
  94. );
  95. NTSTATUS
  96. CnCreateDeviceObjects(
  97. IN PDRIVER_OBJECT DriverObject
  98. );
  99. VOID
  100. CnDeleteDeviceObjects(
  101. VOID
  102. );
  103. VOID
  104. CnAdjustDeviceObjectStackSize(
  105. PDEVICE_OBJECT ClusnetDeviceObject,
  106. PDEVICE_OBJECT TargetDeviceObject
  107. );
  108. //
  109. // Mark init code as discardable.
  110. //
  111. #ifdef ALLOC_PRAGMA
  112. #pragma alloc_text(INIT, DriverEntry)
  113. #pragma alloc_text(INIT, CnCreateDeviceObjects)
  114. #pragma alloc_text(PAGE, DriverUnload)
  115. #pragma alloc_text(PAGE, CnDeleteDeviceObjects)
  116. #endif // ALLOC_PRAGMA
  117. //
  118. // Function definitions
  119. //
  120. NTSTATUS
  121. DriverEntry(
  122. IN PDRIVER_OBJECT DriverObject,
  123. IN PUNICODE_STRING RegistryPath
  124. )
  125. /*++
  126. Routine Description:
  127. Initialization routine for the driver.
  128. Arguments:
  129. DriverObject - Pointer to the driver object created by the system.
  130. RegistryPath - The driver's registry key.
  131. Return Value:
  132. An NT status code.
  133. --*/
  134. {
  135. NTSTATUS status;
  136. USHORT i;
  137. #if DBG
  138. volatile BOOLEAN DontLoad = FALSE;
  139. if ( DontLoad )
  140. return STATUS_UNSUCCESSFUL;
  141. #endif
  142. IF_CNDBG(CN_DEBUG_INIT) {
  143. CNPRINT(("[ClusNet] Loading...\n"));
  144. }
  145. WPP_INIT_TRACING(DriverObject, RegistryPath);
  146. //
  147. // Save a pointer to the system process so that we can open
  148. // handles in the context of this process later.
  149. //
  150. CnSystemProcess = (PKPROCESS) IoGetCurrentProcess();
  151. //
  152. // Allocate a synchronization resource.
  153. //
  154. CnResource = CnAllocatePool(sizeof(ERESOURCE));
  155. if (CnResource == NULL) {
  156. return(STATUS_INSUFFICIENT_RESOURCES);
  157. }
  158. status = ExInitializeResourceLite(CnResource);
  159. if (!NT_SUCCESS(status)) {
  160. goto error_exit;
  161. }
  162. //
  163. // initialize the mechanisms used to deliver event callbacks
  164. // to user mode
  165. //
  166. EventLookasideList = CnAllocatePool(sizeof(NPAGED_LOOKASIDE_LIST));
  167. if (EventLookasideList == NULL) {
  168. status = STATUS_INSUFFICIENT_RESOURCES;
  169. }
  170. ExInitializeNPagedLookasideList(EventLookasideList,
  171. NULL,
  172. NULL,
  173. 0,
  174. sizeof( CLUSNET_EVENT_ENTRY ),
  175. CN_EVENT_SIGNATURE,
  176. 0);
  177. CnInitializeLock( &EventLock, CNP_EVENT_LOCK );
  178. InitializeListHead( &EventFileHandles );
  179. KeInitializeEvent( &EventDeliveryComplete, NotificationEvent, TRUE );
  180. //
  181. // Initialize miscellaneous other items.
  182. //
  183. KeInitializeSpinLock(&CnShutdownLock);
  184. KeInitializeSpinLock(&CnDeviceObjectStackSizeLock);
  185. //
  186. // Initialize the driver object
  187. //
  188. CnDriverObject = DriverObject;
  189. DriverObject->DriverUnload = DriverUnload;
  190. DriverObject->FastIoDispatch = NULL;
  191. for (i=0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
  192. DriverObject->MajorFunction[i] = CnDispatch;
  193. }
  194. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
  195. CnDispatchDeviceControl;
  196. DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
  197. CnDispatchInternalDeviceControl;
  198. //
  199. // Create all the devices exported by this driver.
  200. //
  201. status = CnCreateDeviceObjects(DriverObject);
  202. if (!NT_SUCCESS(status)) {
  203. goto error_exit;
  204. }
  205. #ifdef MEMLOGGING
  206. //
  207. // initialize the in-memory log
  208. //
  209. CnInitializeMemoryLog();
  210. #endif // MEMLOGGING
  211. //
  212. // Load the IP Address and NetBT support.
  213. // This must be done before the transport registers for PnP events.
  214. //
  215. status = IpaLoad();
  216. if (!NT_SUCCESS(status)) {
  217. goto error_exit;
  218. }
  219. status = NbtIfLoad();
  220. if (!NT_SUCCESS(status)) {
  221. goto error_exit;
  222. }
  223. //
  224. // Load the transport component
  225. //
  226. status = CxLoad(RegistryPath);
  227. if (!NT_SUCCESS(status)) {
  228. goto error_exit;
  229. }
  230. #ifdef MM_IN_CLUSNET
  231. //
  232. // Load the membership component
  233. //
  234. status = CmmLoad(RegistryPath);
  235. if (!NT_SUCCESS(status)) {
  236. goto error_exit;
  237. }
  238. #endif // MM_IN_CLUSNET
  239. //
  240. // make ksecdd non-pagable so we can sign and verify
  241. // signatures at raised IRQL
  242. //
  243. SecSetPagingMode( FALSE );
  244. SecurityPagingModeSet = TRUE;
  245. IF_CNDBG(CN_DEBUG_INIT) {
  246. CNPRINT(("[ClusNet] Loaded.\n"));
  247. }
  248. return(STATUS_SUCCESS);
  249. error_exit:
  250. DriverUnload(CnDriverObject);
  251. return(status);
  252. }
  253. VOID
  254. DriverUnload(
  255. IN PDRIVER_OBJECT DriverObject
  256. )
  257. /*++
  258. Routine Description:
  259. Unloads the driver.
  260. Arguments:
  261. DriverObject - Pointer to the driver object created by the system.
  262. Return Value:
  263. None
  264. --*/
  265. {
  266. PAGED_CODE();
  267. IF_CNDBG(CN_DEBUG_INIT) {
  268. CNPRINT(("[ClusNet] Unloading...\n"));
  269. }
  270. CnTrace(HBEAT_ERROR,0, "[ClusNet] Unloading...\n");
  271. //
  272. // First, force a shutdown.
  273. //
  274. CnShutdown();
  275. //
  276. // Now unload the components.
  277. //
  278. #ifdef MM_IN_CLUSNET
  279. CmmUnload();
  280. #endif // MM_IN_CLUSNET
  281. CxUnload();
  282. #ifdef MEMLOGGING
  283. //
  284. // initialize the in-memory log
  285. //
  286. CnFreeMemoryLog();
  287. #endif // MEMLOGGING
  288. CnDeleteDeviceObjects();
  289. if (CnResource != NULL) {
  290. ExDeleteResourceLite(CnResource);
  291. CnFreePool(CnResource); CnResource = NULL;
  292. }
  293. CnDriverObject = NULL;
  294. IF_CNDBG(CN_DEBUG_INIT) {
  295. CNPRINT(("[ClusNet] Unloaded.\n"));
  296. }
  297. if (EventLookasideList != NULL) {
  298. ExDeleteNPagedLookasideList( EventLookasideList );
  299. CnFreePool( EventLookasideList ); EventLookasideList = NULL;
  300. }
  301. //
  302. // finally, allow the security driver to return to nonpaged mode
  303. //
  304. if ( SecurityPagingModeSet ) {
  305. SecSetPagingMode( TRUE );
  306. }
  307. WPP_CLEANUP(DriverObject);
  308. return;
  309. } // DriverUnload
  310. NTSTATUS
  311. CnCreateDeviceObjects(
  312. IN PDRIVER_OBJECT DriverObject
  313. )
  314. /*++
  315. Routine Description:
  316. Creates the device objects exported by the driver.
  317. Arguments:
  318. DriverObject - Pointer to the driver object created by the system.
  319. Return Value:
  320. An NT status code.
  321. --*/
  322. {
  323. NTSTATUS status;
  324. UNICODE_STRING deviceName;
  325. //
  326. // Create the driver control device
  327. //
  328. RtlInitUnicodeString(&deviceName, DD_CLUSNET_DEVICE_NAME);
  329. status = IoCreateDevice(
  330. DriverObject,
  331. 0,
  332. &deviceName,
  333. FILE_DEVICE_NETWORK,
  334. 0,
  335. FALSE,
  336. &CnDeviceObject
  337. );
  338. if (!NT_SUCCESS(status)) {
  339. CNPRINT((
  340. "[ClusNet] Failed to create %ws device object, status %lx\n",
  341. deviceName.Buffer,
  342. status
  343. ));
  344. return(status);
  345. }
  346. CnDeviceObject->Flags |= DO_DIRECT_IO;
  347. CnDeviceObject->StackSize = CN_DEFAULT_IRP_STACK_SIZE;
  348. status = IoRegisterShutdownNotification(CnDeviceObject);
  349. if (!NT_SUCCESS(status)) {
  350. CNPRINT((
  351. "[ClusNet] Failed to register for shutdown notification, status %lx\n",
  352. status
  353. ));
  354. }
  355. #if defined(WMI_TRACING)
  356. status = IoWMIRegistrationControl (CnDeviceObject, WMIREG_ACTION_REGISTER);
  357. if (!NT_SUCCESS(status)) {
  358. CNPRINT(("[ClusNet] Failed to register for WMI Support, %lx\n", status) );
  359. }
  360. #endif
  361. //
  362. // Create the datagram transport device
  363. //
  364. RtlInitUnicodeString(&deviceName, DD_CDP_DEVICE_NAME);
  365. status = IoCreateDevice(
  366. DriverObject,
  367. 0,
  368. &deviceName,
  369. FILE_DEVICE_NETWORK,
  370. 0,
  371. FALSE,
  372. &CdpDeviceObject
  373. );
  374. if (!NT_SUCCESS(status)) {
  375. CNPRINT((
  376. "[ClusNet] Failed to create %ws device object, status %lx\n",
  377. deviceName.Buffer,
  378. status
  379. ));
  380. return(status);
  381. }
  382. CdpDeviceObject->Flags |= DO_DIRECT_IO;
  383. CdpDeviceObject->StackSize = CDP_DEFAULT_IRP_STACK_SIZE;
  384. return(STATUS_SUCCESS);
  385. }
  386. VOID
  387. CnDeleteDeviceObjects(
  388. VOID
  389. )
  390. /*++
  391. Routine Description:
  392. Deletes the device objects exported by the driver.
  393. Arguments:
  394. None.
  395. Return Value:
  396. None.
  397. --*/
  398. {
  399. PAGED_CODE();
  400. if (CnDeviceObject != NULL) {
  401. #if defined(WMI_TRACING)
  402. IoWMIRegistrationControl(CnDeviceObject, WMIREG_ACTION_DEREGISTER);
  403. #endif
  404. IoDeleteDevice(CnDeviceObject);
  405. CnDeviceObject = NULL;
  406. }
  407. if (CdpDeviceObject != NULL) {
  408. IoDeleteDevice(CdpDeviceObject);
  409. CdpDeviceObject = NULL;
  410. }
  411. return;
  412. }
  413. NTSTATUS
  414. CnInitialize(
  415. IN CL_NODE_ID LocalNodeId,
  416. IN ULONG MaxNodes
  417. )
  418. /*++
  419. Routine Description:
  420. Initialization routine for the Cluster Network Driver.
  421. Called when an initialize request is received.
  422. Arguments:
  423. LocalNodeId - The ID of the local node.
  424. MaxNodes - The maximum number of valid cluster nodes.
  425. Return Value:
  426. An NT status code.
  427. --*/
  428. {
  429. NTSTATUS status;
  430. KIRQL irql;
  431. if ( (MaxNodes == 0) ||
  432. (LocalNodeId < ClusterMinNodeId) ||
  433. (LocalNodeId > (ClusterMinNodeId + MaxNodes - 1))
  434. )
  435. {
  436. return(STATUS_INVALID_PARAMETER);
  437. }
  438. IF_CNDBG(CN_DEBUG_INIT) {
  439. CNPRINT(("[Clusnet] Initializing...\n"));
  440. }
  441. CnState = CnStateInitializePending;
  442. //
  443. // Reset global values
  444. //
  445. CnAssert(CnLocalNodeId == ClusterInvalidNodeId);
  446. CnAssert(CnMinValidNodeId == ClusterInvalidNodeId);
  447. CnAssert(CnMaxValidNodeId == ClusterInvalidNodeId);
  448. CnMinValidNodeId = ClusterMinNodeId;
  449. CnMaxValidNodeId = ClusterMinNodeId + MaxNodes - 1;
  450. CnLocalNodeId = LocalNodeId;
  451. //
  452. // Reenable the halt processing mechanism.
  453. //
  454. KeAcquireSpinLock(&CnShutdownLock, &irql);
  455. CnShutdownScheduled = FALSE;
  456. CnShutdownEvent = NULL;
  457. KeReleaseSpinLock(&CnShutdownLock, irql);
  458. //
  459. // Initialize the IP Address support
  460. //
  461. status = IpaInitialize();
  462. if (status != STATUS_SUCCESS) {
  463. goto error_exit;
  464. }
  465. #ifdef MM_IN_CLUSNET
  466. //
  467. // Call the Membership Manager's init routine. This will in turn call
  468. // the Transport's init routine.
  469. //
  470. status = CmmInitialize();
  471. #else // MM_IN_CLUSNET
  472. status = CxInitialize();
  473. #endif // MM_IN_CLUSNET
  474. if (status == STATUS_SUCCESS) {
  475. IF_CNDBG(CN_DEBUG_INIT) {
  476. CNPRINT(("[Clusnet] Initialized.\n"));
  477. }
  478. CnState = CnStateInitialized;
  479. }
  480. else {
  481. goto error_exit;
  482. }
  483. return(STATUS_SUCCESS);
  484. error_exit:
  485. IF_CNDBG(CN_DEBUG_INIT) {
  486. CNPRINT(("[Clusnet] Initialization failed, Shutting down. Status = %08X\n",
  487. status));
  488. }
  489. CnShutdown();
  490. return(status);
  491. } // CnInitialize
  492. NTSTATUS
  493. CnShutdown(
  494. VOID
  495. )
  496. /*++
  497. Routine Description:
  498. Terminates operation of the Cluster Membership Manager.
  499. Called when the Cluster Service is shutting down.
  500. Arguments:
  501. None.
  502. Return Value:
  503. None.
  504. --*/
  505. {
  506. NTSTATUS status;
  507. if ( (CnState == CnStateInitialized) ||
  508. (CnState == CnStateInitializePending)
  509. )
  510. {
  511. IF_CNDBG(CN_DEBUG_INIT) {
  512. CNPRINT(("[Clusnet] Shutting down...\n"));
  513. }
  514. CnState = CnStateShutdownPending;
  515. //
  516. // Shutdown the NetBT and IP Address support.
  517. //
  518. NbtIfShutdown();
  519. IpaShutdown();
  520. #ifdef MM_IN_CLUSNET
  521. //
  522. // Shutdown the Membership Manager. This will shutdown the
  523. // Transport as a side-effect.
  524. //
  525. CmmShutdown();
  526. #else // MM_IN_CLUSNET
  527. CxShutdown();
  528. #endif // MM_IN_CLUSNET
  529. IF_CNDBG(CN_DEBUG_INIT) {
  530. CNPRINT(("[Clusnet] Shutdown complete.\n"));
  531. }
  532. CnAssert(CnLocalNodeId != ClusterInvalidNodeId);
  533. CnMinValidNodeId = ClusterInvalidNodeId;
  534. CnMaxValidNodeId = ClusterInvalidNodeId;
  535. CnLocalNodeId = ClusterInvalidNodeId;
  536. CnState = CnStateShutdown;
  537. status = STATUS_SUCCESS;
  538. }
  539. else {
  540. status = STATUS_DEVICE_NOT_READY;
  541. }
  542. //
  543. // always test if we have a handle to this process
  544. // and remove it
  545. //
  546. if ( ClussvcProcessHandle ) {
  547. CnCloseProcessHandle( ClussvcProcessHandle );
  548. ClussvcProcessHandle = NULL;
  549. }
  550. return(status);
  551. } // CnShutdown
  552. VOID
  553. CnShutdownWorkRoutine(
  554. IN PVOID WorkItem
  555. )
  556. {
  557. BOOLEAN acquired;
  558. NTSTATUS Status;
  559. acquired = CnAcquireResourceExclusive(CnResource, TRUE);
  560. if (!acquired) {
  561. KIRQL irql;
  562. CNPRINT(("[Clusnet] Failed to acquire CnResource\n"));
  563. KeAcquireSpinLock(&CnShutdownLock, &irql);
  564. CnShutdownScheduled = FALSE;
  565. if (CnShutdownEvent != NULL) {
  566. KeSetEvent(CnShutdownEvent, IO_NO_INCREMENT, FALSE);
  567. }
  568. KeReleaseSpinLock(&CnShutdownLock, irql);
  569. return;
  570. }
  571. (VOID) CnShutdown();
  572. if (CnShutdownEvent != NULL) {
  573. KeSetEvent(CnShutdownEvent, IO_NO_INCREMENT, FALSE);
  574. }
  575. if (acquired) {
  576. CnReleaseResourceForThread(
  577. CnResource,
  578. (ERESOURCE_THREAD) PsGetCurrentThread()
  579. );
  580. }
  581. //
  582. // Leave CnShutdownScheduled = TRUE until we are reinitialized to
  583. // prevent scheduling unnecessary work items.
  584. //
  585. return;
  586. } // CnShutdownWorkRoutine
  587. BOOLEAN
  588. CnHaltOperation(
  589. IN PKEVENT ShutdownEvent OPTIONAL
  590. )
  591. /*++
  592. Routine Description:
  593. Schedules a critical worker thread to perform clusnet shutdown,
  594. if a thread is not already scheduled.
  595. Arguments:
  596. ShutdownEvent - if provided, event to be signalled after
  597. shutdown is complete
  598. Return value:
  599. TRUE if shutdown was scheduled. FALSE if shutdown was already
  600. scheduled (in which case ShutdownEvent will not be signalled).
  601. --*/
  602. {
  603. KIRQL irql;
  604. KeAcquireSpinLock(&CnShutdownLock, &irql);
  605. if (CnShutdownScheduled) {
  606. KeReleaseSpinLock(&CnShutdownLock, irql);
  607. return(FALSE);
  608. }
  609. CnShutdownScheduled = TRUE;
  610. CnShutdownEvent = ShutdownEvent;
  611. KeReleaseSpinLock(&CnShutdownLock, irql);
  612. //
  613. // Schedule a critical worker thread to do the shutdown work.
  614. //
  615. ExInitializeWorkItem(
  616. &CnShutdownWorkItem,
  617. CnShutdownWorkRoutine,
  618. &CnShutdownWorkItem
  619. );
  620. ExQueueWorkItem(&CnShutdownWorkItem, CriticalWorkQueue);
  621. return(TRUE);
  622. } // CnHaltOperation
  623. //
  624. // ExResource wrappers that disable APCs.
  625. //
  626. BOOLEAN
  627. CnAcquireResourceExclusive(
  628. IN PERESOURCE Resource,
  629. IN BOOLEAN Wait
  630. )
  631. {
  632. BOOLEAN acquired;
  633. KeEnterCriticalRegion();
  634. acquired = ExAcquireResourceExclusiveLite(Resource, Wait);
  635. if (!acquired) {
  636. KeLeaveCriticalRegion();
  637. }
  638. return(acquired);
  639. } // CnAcquireResourceExclusive
  640. BOOLEAN
  641. CnAcquireResourceShared(
  642. IN PERESOURCE Resource,
  643. IN BOOLEAN Wait
  644. )
  645. {
  646. BOOLEAN acquired;
  647. KeEnterCriticalRegion();
  648. acquired = ExAcquireResourceSharedLite(Resource, Wait);
  649. if (!acquired) {
  650. KeLeaveCriticalRegion();
  651. }
  652. return(acquired);
  653. } // CnAcquireResourceShared
  654. VOID
  655. CnReleaseResourceForThread(
  656. IN PERESOURCE Resource,
  657. IN ERESOURCE_THREAD ResourceThreadId
  658. )
  659. {
  660. ExReleaseResourceForThreadLite(Resource, ResourceThreadId);
  661. KeLeaveCriticalRegion();
  662. return;
  663. } // CnReleaseResourceForThread
  664. NTSTATUS
  665. CnCloseProcessHandle(
  666. HANDLE Handle
  667. )
  668. /*++
  669. Routine Description:
  670. Close the cluster service process handle
  671. Arguments:
  672. None
  673. Return Value:
  674. None
  675. --*/
  676. {
  677. NTSTATUS Status = STATUS_SUCCESS;
  678. CnAssert( Handle != NULL );
  679. KeAttachProcess( CnSystemProcess );
  680. Status = ZwClose( Handle );
  681. KeDetachProcess();
  682. IF_CNDBG(CN_DEBUG_INIT) {
  683. CNPRINT(("[Clusnet] Process handle released. status = %08X\n", Status));
  684. }
  685. return Status;
  686. }
  687. VOID
  688. CnAdjustDeviceObjectStackSize(
  689. PDEVICE_OBJECT ClusnetDeviceObject,
  690. PDEVICE_OBJECT TargetDeviceObject
  691. )
  692. /*++
  693. Routine Description
  694. Adjust the StackSize of ClusnetDeviceObject so that we
  695. can pass client IRPs down to TargetDeviceObject.
  696. The StackSize of clusnet device objects is initialized to
  697. a default that allows for some leeway for attached drivers.
  698. Arguments
  699. ClusnetDeviceObject - clusnet device object whose StackSize
  700. should be adjusted
  701. TargetDeviceObject - device object clusnet IRPs, originally
  702. issued to clusnet, will be forwarded to
  703. Return value
  704. None
  705. --*/
  706. {
  707. CCHAR defaultStackSize, newStackSize = 0;
  708. KIRQL irql;
  709. if (ClusnetDeviceObject == CnDeviceObject) {
  710. defaultStackSize = CN_DEFAULT_IRP_STACK_SIZE;
  711. }
  712. else if (ClusnetDeviceObject == CdpDeviceObject) {
  713. defaultStackSize = CDP_DEFAULT_IRP_STACK_SIZE;
  714. }
  715. else {
  716. IF_CNDBG(CN_DEBUG_INIT) {
  717. CNPRINT(("[Clusnet] CnAdjustDeviceObjectStackSize: "
  718. "unknown clusnet device object %p.\n",
  719. ClusnetDeviceObject
  720. ));
  721. }
  722. return;
  723. }
  724. KeAcquireSpinLock(&CnDeviceObjectStackSizeLock, &irql);
  725. if (ClusnetDeviceObject->StackSize <
  726. TargetDeviceObject->StackSize + defaultStackSize) {
  727. ClusnetDeviceObject->StackSize =
  728. TargetDeviceObject->StackSize + defaultStackSize;
  729. IF_CNDBG(CN_DEBUG_INIT) {
  730. newStackSize = ClusnetDeviceObject->StackSize;
  731. }
  732. }
  733. KeReleaseSpinLock(&CnDeviceObjectStackSizeLock, irql);
  734. IF_CNDBG(CN_DEBUG_INIT) {
  735. if (newStackSize != 0) {
  736. CNPRINT(("[Clusnet] Set StackSize of clusnet device "
  737. "object %p to %d "
  738. "based on target device object %p.\n",
  739. ClusnetDeviceObject,
  740. newStackSize,
  741. TargetDeviceObject
  742. ));
  743. }
  744. }
  745. return;
  746. } // CnAdjustDeviceObjectStackSize
  747. #if DBG
  748. //
  749. // Debug code.
  750. //
  751. ULONG CnCpuLockMask[MAXIMUM_PROCESSORS];
  752. VOID
  753. CnAssertBreak(
  754. PCHAR FailedStatement,
  755. PCHAR FileName,
  756. ULONG LineNumber
  757. )
  758. {
  759. DbgPrint(
  760. "[Clusnet] Assertion \"%s\" failed in %s line %u\n",
  761. FailedStatement,
  762. FileName,
  763. LineNumber
  764. );
  765. DbgBreakPoint();
  766. return;
  767. } // CnAssertBreak
  768. ULONG
  769. CnGetCpuLockMask(
  770. VOID
  771. )
  772. {
  773. ULONG mask;
  774. if (KeGetCurrentIrql() != DISPATCH_LEVEL) {
  775. CnAssert(CnCpuLockMask[KeGetCurrentProcessorNumber()] == 0);
  776. mask = 0;
  777. }
  778. else {
  779. mask = CnCpuLockMask[KeGetCurrentProcessorNumber()];
  780. }
  781. return(mask);
  782. }
  783. VOID
  784. CnVerifyCpuLockMask(
  785. IN ULONG RequiredLockMask,
  786. IN ULONG ForbiddenLockMask,
  787. IN ULONG MaximumLockMask
  788. )
  789. {
  790. ULONG mask;
  791. if (KeGetCurrentIrql() < DISPATCH_LEVEL) {
  792. mask = 0;
  793. }
  794. else {
  795. mask = CnCpuLockMask[KeGetCurrentProcessorNumber()];
  796. }
  797. if ((mask & RequiredLockMask) != RequiredLockMask) {
  798. CNPRINT((
  799. "[Clusnet] Locking bug: Req'd lock mask %lx, actual mask %lx\n",
  800. RequiredLockMask,
  801. mask
  802. ));
  803. DbgBreakPoint();
  804. }
  805. if (mask & ForbiddenLockMask) {
  806. CNPRINT((
  807. "[Clusnet] Locking bug: Forbidden mask %lx, actual mask %lx\n",
  808. ForbiddenLockMask,
  809. mask
  810. ));
  811. DbgBreakPoint();
  812. }
  813. if (mask > MaximumLockMask) {
  814. CNPRINT((
  815. "[Clusnet] Locking bug: Max lock mask %lx, actual mask %lx\n",
  816. MaximumLockMask,
  817. mask
  818. ));
  819. DbgBreakPoint();
  820. }
  821. return;
  822. }
  823. VOID
  824. CnInitializeLock(
  825. PCN_LOCK Lock,
  826. ULONG Rank
  827. )
  828. {
  829. KeInitializeSpinLock(&(Lock->SpinLock));
  830. Lock->Rank = Rank;
  831. return;
  832. }
  833. VOID
  834. CnAcquireLock(
  835. IN PCN_LOCK Lock,
  836. OUT PCN_IRQL Irql
  837. )
  838. {
  839. KIRQL irql;
  840. ULONG currentCpu;
  841. if (KeGetCurrentIrql() != DISPATCH_LEVEL) {
  842. KeRaiseIrql(DISPATCH_LEVEL, &irql);
  843. }
  844. else {
  845. irql = DISPATCH_LEVEL;
  846. }
  847. currentCpu = KeGetCurrentProcessorNumber();
  848. if (CnCpuLockMask[currentCpu] >= Lock->Rank) {
  849. CNPRINT((
  850. "[Clusnet] CPU %u trying to acquire lock %lx out of order, mask %lx\n",
  851. currentCpu,
  852. Lock->Rank,
  853. CnCpuLockMask[currentCpu]
  854. ));
  855. DbgBreakPoint();
  856. }
  857. KeAcquireSpinLockAtDpcLevel(&(Lock->SpinLock));
  858. *Irql = irql;
  859. CnCpuLockMask[currentCpu] |= Lock->Rank;
  860. return;
  861. }
  862. VOID
  863. CnAcquireLockAtDpc(
  864. IN PCN_LOCK Lock
  865. )
  866. {
  867. ULONG currentCpu = KeGetCurrentProcessorNumber();
  868. if (KeGetCurrentIrql() != DISPATCH_LEVEL) {
  869. CNPRINT((
  870. "[Clusnet] CPU %u trying to acquire DPC lock at passive level.\n",
  871. currentCpu
  872. ));
  873. DbgBreakPoint();
  874. }
  875. if (CnCpuLockMask[currentCpu] >= Lock->Rank) {
  876. CNPRINT((
  877. "[Clusnet] CPU %u trying to acquire lock %lx out of order, mask %lx\n",
  878. currentCpu,
  879. Lock->Rank,
  880. CnCpuLockMask[currentCpu]
  881. ));
  882. DbgBreakPoint();
  883. }
  884. KeAcquireSpinLockAtDpcLevel(&(Lock->SpinLock));
  885. CnCpuLockMask[currentCpu] |= Lock->Rank;
  886. return;
  887. }
  888. VOID
  889. CnReleaseLock(
  890. IN PCN_LOCK Lock,
  891. IN CN_IRQL Irql
  892. )
  893. {
  894. ULONG currentCpu = KeGetCurrentProcessorNumber();
  895. if (KeGetCurrentIrql() != DISPATCH_LEVEL) {
  896. CNPRINT((
  897. "[Clusnet] CPU %u trying to release lock from passive level.\n",
  898. currentCpu
  899. ));
  900. DbgBreakPoint();
  901. }
  902. if ( !(CnCpuLockMask[currentCpu] & Lock->Rank) ) {
  903. CNPRINT((
  904. "[Clusnet] CPU %u trying to release lock %lx, which it doesn't hold, mask %lx\n",
  905. currentCpu,
  906. Lock->Rank,
  907. CnCpuLockMask[currentCpu]
  908. ));
  909. DbgBreakPoint();
  910. }
  911. CnCpuLockMask[currentCpu] &= ~(Lock->Rank);
  912. KeReleaseSpinLock(&(Lock->SpinLock), Irql);
  913. return;
  914. }
  915. VOID
  916. CnReleaseLockFromDpc(
  917. IN PCN_LOCK Lock
  918. )
  919. {
  920. ULONG currentCpu = KeGetCurrentProcessorNumber();
  921. if (KeGetCurrentIrql() != DISPATCH_LEVEL) {
  922. CNPRINT((
  923. "[Clusnet] CPU %u trying to release lock from passive level.\n",
  924. currentCpu
  925. ));
  926. DbgBreakPoint();
  927. }
  928. if ( !(CnCpuLockMask[currentCpu] & Lock->Rank) ) {
  929. CNPRINT((
  930. "[Clusnet] CPU %u trying to release lock %lx, which it doesn't hold, mask %lx\n",
  931. currentCpu,
  932. Lock->Rank,
  933. CnCpuLockMask[currentCpu]
  934. ));
  935. DbgBreakPoint();
  936. }
  937. CnCpuLockMask[currentCpu] &= ~(Lock->Rank);
  938. KeReleaseSpinLockFromDpcLevel(&(Lock->SpinLock));
  939. return;
  940. }
  941. VOID
  942. CnMarkIoCancelLockAcquired(
  943. VOID
  944. )
  945. {
  946. ULONG currentCpu = KeGetCurrentProcessorNumber();
  947. CnAssert(KeGetCurrentIrql() == DISPATCH_LEVEL);
  948. CnAssert(!(CnCpuLockMask[currentCpu] & CN_IOCANCEL_LOCK));
  949. CnAssert(CnCpuLockMask[currentCpu] < CN_IOCANCEL_LOCK_MAX);
  950. CnCpuLockMask[currentCpu] |= CN_IOCANCEL_LOCK;
  951. return;
  952. }
  953. VOID
  954. CnAcquireCancelSpinLock(
  955. OUT PCN_IRQL Irql
  956. )
  957. {
  958. KIRQL irql;
  959. KIRQL tempIrql;
  960. ULONG currentCpu;
  961. if (KeGetCurrentIrql() != DISPATCH_LEVEL) {
  962. KeRaiseIrql(DISPATCH_LEVEL, &irql);
  963. }
  964. else {
  965. irql = DISPATCH_LEVEL;
  966. }
  967. currentCpu = KeGetCurrentProcessorNumber();
  968. if (CnCpuLockMask[currentCpu] >= CN_IOCANCEL_LOCK) {
  969. CNPRINT((
  970. "[Clusnet] CPU %u trying to acquire IoCancel lock out of order, mask %lx\n",
  971. currentCpu,
  972. CnCpuLockMask[currentCpu]
  973. ));
  974. DbgBreakPoint();
  975. }
  976. IoAcquireCancelSpinLock(&tempIrql);
  977. CnAssert(tempIrql == DISPATCH_LEVEL);
  978. *Irql = irql;
  979. CnCpuLockMask[currentCpu] |= CN_IOCANCEL_LOCK;
  980. return;
  981. }
  982. VOID
  983. CnReleaseCancelSpinLock(
  984. IN CN_IRQL Irql
  985. )
  986. {
  987. ULONG currentCpu = KeGetCurrentProcessorNumber();
  988. if (KeGetCurrentIrql() != DISPATCH_LEVEL) {
  989. CNPRINT((
  990. "[Clusnet] CPU %u trying to release lock from passive level.\n",
  991. currentCpu
  992. ));
  993. DbgBreakPoint();
  994. }
  995. if ( !(CnCpuLockMask[currentCpu] & CN_IOCANCEL_LOCK) ) {
  996. CNPRINT((
  997. "[Clusnet] CPU %u trying to release IoCancel lock, which it doesn't hold, mask %lx\n",
  998. currentCpu,
  999. CnCpuLockMask[currentCpu]
  1000. ));
  1001. DbgBreakPoint();
  1002. }
  1003. CnCpuLockMask[currentCpu] &= ~(CN_IOCANCEL_LOCK);
  1004. IoReleaseCancelSpinLock(Irql);
  1005. return;
  1006. }
  1007. #endif // DEBUG