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.

3026 lines
71 KiB

  1. /*++
  2. Copyright (c) 1996-2000 Microsoft Corporation
  3. Module Name:
  4. cnapi.c
  5. Abstract:
  6. Cluster Network configuration APIs
  7. Author:
  8. Mike Massa (mikemas) 18-Mar-1996
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. --*/
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <windows.h>
  17. #include <clusapi.h>
  18. #include <clusdef.h>
  19. #include <ntddcnet.h>
  20. #include <cnettest.h>
  21. #include <cnetapi.h>
  22. #include <clusrtl.h>
  23. #include <winsock2.h>
  24. #include <tdi.h>
  25. #include <align.h>
  26. //
  27. // Private Support Routines.
  28. //
  29. static NTSTATUS
  30. OpenDevice(
  31. HANDLE *Handle,
  32. LPWSTR DeviceName,
  33. ULONG ShareAccess
  34. )
  35. /*++
  36. Routine Description:
  37. This function opens a specified IO device.
  38. Arguments:
  39. Handle - pointer to location where the opened device Handle is
  40. returned.
  41. DriverName - name of the device to be opened.
  42. Return Value:
  43. Windows Error Code.
  44. --*/
  45. {
  46. OBJECT_ATTRIBUTES objectAttributes;
  47. IO_STATUS_BLOCK ioStatusBlock;
  48. UNICODE_STRING nameString;
  49. NTSTATUS status;
  50. *Handle = NULL;
  51. //
  52. // Open a Handle to the device.
  53. //
  54. RtlInitUnicodeString(&nameString, DeviceName);
  55. InitializeObjectAttributes(
  56. &objectAttributes,
  57. &nameString,
  58. OBJ_CASE_INSENSITIVE,
  59. (HANDLE) NULL,
  60. (PSECURITY_DESCRIPTOR) NULL
  61. );
  62. status = NtCreateFile(
  63. Handle,
  64. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  65. &objectAttributes,
  66. &ioStatusBlock,
  67. NULL,
  68. FILE_ATTRIBUTE_NORMAL,
  69. ShareAccess,
  70. FILE_OPEN_IF,
  71. 0,
  72. NULL,
  73. 0
  74. );
  75. return(status);
  76. } // OpenDevice
  77. NTSTATUS
  78. DoIoctl(
  79. IN HANDLE Handle,
  80. IN DWORD IoctlCode,
  81. IN PVOID Request,
  82. IN DWORD RequestSize,
  83. IN PVOID Response,
  84. IN OUT PDWORD ResponseSize,
  85. IN LPOVERLAPPED Overlapped
  86. )
  87. /*++
  88. Routine Description:
  89. Packages and issues an ioctl.
  90. Arguments:
  91. Handle - An open file Handle on which to issue the request.
  92. IoctlCode - The IOCTL opcode.
  93. Request - A pointer to the input buffer.
  94. RequestSize - Size of the input buffer.
  95. Response - A pointer to the output buffer.
  96. ResponseSize - On input, the size in bytes of the output buffer.
  97. On output, the number of bytes returned in the output buffer.
  98. Return Value:
  99. NT Status Code.
  100. --*/
  101. {
  102. NTSTATUS status;
  103. if (ARGUMENT_PRESENT(Overlapped)) {
  104. Overlapped->Internal = (ULONG_PTR) STATUS_PENDING;
  105. status = NtDeviceIoControlFile(
  106. Handle,
  107. Overlapped->hEvent,
  108. NULL,
  109. (((DWORD_PTR) Overlapped->hEvent) & 1) ? NULL : Overlapped,
  110. (PIO_STATUS_BLOCK) &(Overlapped->Internal),
  111. IoctlCode,
  112. Request,
  113. RequestSize,
  114. Response,
  115. *ResponseSize
  116. );
  117. }
  118. else {
  119. IO_STATUS_BLOCK ioStatusBlock = {0, 0};
  120. HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
  121. if (event != NULL) {
  122. //
  123. // Prevent operation from completing to a completion port.
  124. //
  125. event = (HANDLE) (((ULONG_PTR) event) | 1);
  126. status = NtDeviceIoControlFile(
  127. Handle,
  128. event,
  129. NULL,
  130. NULL,
  131. &ioStatusBlock,
  132. IoctlCode,
  133. Request,
  134. RequestSize,
  135. Response,
  136. *ResponseSize
  137. );
  138. if (status == STATUS_PENDING) {
  139. status = NtWaitForSingleObject(
  140. event,
  141. TRUE,
  142. NULL
  143. );
  144. }
  145. if (status == STATUS_SUCCESS) {
  146. status = ioStatusBlock.Status;
  147. // NOTENOTE: on 64 bit this truncates might want to add > code
  148. *ResponseSize = (ULONG)ioStatusBlock.Information;
  149. }
  150. else {
  151. *ResponseSize = 0;
  152. }
  153. CloseHandle(event);
  154. }
  155. else {
  156. status = GetLastError();
  157. }
  158. }
  159. return(status);
  160. } // DoIoctl
  161. #define FACILITY_CODE_MASK 0x0FFF0000
  162. #define FACILITY_CODE_SHIFT 16
  163. #define SHIFTED_FACILITY_CLUSTER (FACILITY_CLUSTER_ERROR_CODE << FACILITY_CODE_SHIFT)
  164. DWORD
  165. NtStatusToClusnetError(
  166. NTSTATUS Status
  167. )
  168. {
  169. DWORD dosStatus;
  170. if ( !((Status & FACILITY_CODE_MASK) == SHIFTED_FACILITY_CLUSTER) ) {
  171. dosStatus = RtlNtStatusToDosError(Status);
  172. }
  173. else {
  174. //dosStatus = (DWORD) Status;
  175. switch ( Status ) {
  176. case STATUS_CLUSTER_INVALID_NODE:
  177. dosStatus = ERROR_CLUSTER_INVALID_NODE;
  178. break;
  179. case STATUS_CLUSTER_NODE_EXISTS:
  180. dosStatus = ERROR_CLUSTER_NODE_EXISTS;
  181. break;
  182. case STATUS_CLUSTER_JOIN_IN_PROGRESS:
  183. dosStatus = ERROR_CLUSTER_JOIN_IN_PROGRESS;
  184. break;
  185. case STATUS_CLUSTER_NODE_NOT_FOUND:
  186. dosStatus = ERROR_CLUSTER_NODE_NOT_FOUND;
  187. break;
  188. case STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND:
  189. dosStatus = ERROR_CLUSTER_LOCAL_NODE_NOT_FOUND;
  190. break;
  191. case STATUS_CLUSTER_NETWORK_EXISTS:
  192. dosStatus = ERROR_CLUSTER_NETWORK_EXISTS;
  193. break;
  194. case STATUS_CLUSTER_NETWORK_NOT_FOUND:
  195. dosStatus = ERROR_CLUSTER_NETWORK_NOT_FOUND;
  196. break;
  197. case STATUS_CLUSTER_NETINTERFACE_EXISTS:
  198. dosStatus = ERROR_CLUSTER_NETINTERFACE_EXISTS;
  199. break;
  200. case STATUS_CLUSTER_NETINTERFACE_NOT_FOUND:
  201. dosStatus =ERROR_CLUSTER_NETINTERFACE_NOT_FOUND;
  202. break;
  203. case STATUS_CLUSTER_INVALID_REQUEST:
  204. dosStatus = ERROR_CLUSTER_INVALID_REQUEST;
  205. break;
  206. case STATUS_CLUSTER_INVALID_NETWORK_PROVIDER:
  207. dosStatus = ERROR_CLUSTER_INVALID_NETWORK_PROVIDER;
  208. break;
  209. case STATUS_CLUSTER_NODE_DOWN:
  210. dosStatus = ERROR_CLUSTER_NODE_DOWN;
  211. break;
  212. case STATUS_CLUSTER_NODE_UNREACHABLE:
  213. dosStatus = ERROR_CLUSTER_NODE_UNREACHABLE;
  214. break;
  215. case STATUS_CLUSTER_NODE_NOT_MEMBER:
  216. dosStatus = ERROR_CLUSTER_NODE_NOT_MEMBER;
  217. break;
  218. case STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS:
  219. dosStatus = ERROR_CLUSTER_JOIN_NOT_IN_PROGRESS;
  220. break;
  221. case STATUS_CLUSTER_INVALID_NETWORK:
  222. dosStatus = ERROR_CLUSTER_INVALID_NETWORK;
  223. break;
  224. case STATUS_CLUSTER_NODE_UP:
  225. dosStatus = ERROR_CLUSTER_NODE_UP;
  226. break;
  227. case STATUS_CLUSTER_NODE_NOT_PAUSED:
  228. dosStatus = ERROR_CLUSTER_NODE_NOT_PAUSED;
  229. break;
  230. case STATUS_CLUSTER_NO_SECURITY_CONTEXT:
  231. dosStatus = ERROR_CLUSTER_NO_SECURITY_CONTEXT;
  232. break;
  233. case STATUS_CLUSTER_NETWORK_NOT_INTERNAL:
  234. dosStatus = ERROR_CLUSTER_NETWORK_NOT_INTERNAL;
  235. break;
  236. case STATUS_CLUSTER_NODE_ALREADY_UP:
  237. dosStatus = ERROR_CLUSTER_NODE_ALREADY_UP;
  238. break;
  239. case STATUS_CLUSTER_NODE_ALREADY_DOWN:
  240. dosStatus = ERROR_CLUSTER_NODE_ALREADY_DOWN;
  241. break;
  242. case STATUS_CLUSTER_NETWORK_ALREADY_ONLINE:
  243. dosStatus = ERROR_CLUSTER_NETWORK_ALREADY_ONLINE;
  244. break;
  245. case STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE:
  246. dosStatus = ERROR_CLUSTER_NETWORK_ALREADY_OFFLINE;
  247. break;
  248. case STATUS_CLUSTER_NODE_ALREADY_MEMBER:
  249. dosStatus = ERROR_CLUSTER_NODE_ALREADY_MEMBER;
  250. break;
  251. default:
  252. dosStatus = (DWORD)Status;
  253. break;
  254. }
  255. }
  256. return(dosStatus);
  257. }
  258. //
  259. // Public Routines
  260. //
  261. HANDLE
  262. ClusnetOpenControlChannel(
  263. IN ULONG ShareAccess
  264. )
  265. {
  266. HANDLE handle = NULL;
  267. DWORD status;
  268. status = OpenDevice(&handle, L"\\Device\\ClusterNetwork", ShareAccess);
  269. if (status != ERROR_SUCCESS) {
  270. SetLastError(NtStatusToClusnetError(status));
  271. }
  272. return(handle);
  273. } // ClusnetOpenControlChannel
  274. DWORD
  275. ClusnetEnableShutdownOnClose(
  276. IN HANDLE ControlChannel
  277. )
  278. {
  279. NTSTATUS status;
  280. ULONG responseSize = 0;
  281. CLUSNET_SHUTDOWN_ON_CLOSE_REQUEST request;
  282. DWORD requestSize = sizeof(request);
  283. request.ProcessId = GetCurrentProcessId();
  284. status = DoIoctl(
  285. ControlChannel,
  286. IOCTL_CLUSNET_ENABLE_SHUTDOWN_ON_CLOSE,
  287. &request,
  288. requestSize,
  289. NULL,
  290. &responseSize,
  291. NULL
  292. );
  293. return(NtStatusToClusnetError(status));
  294. } // ClusnetEnableShutdownOnClose
  295. DWORD
  296. ClusnetDisableShutdownOnClose(
  297. IN HANDLE ControlChannel
  298. )
  299. {
  300. NTSTATUS status;
  301. ULONG responseSize = 0;
  302. status = DoIoctl(
  303. ControlChannel,
  304. IOCTL_CLUSNET_DISABLE_SHUTDOWN_ON_CLOSE,
  305. NULL,
  306. 0,
  307. NULL,
  308. &responseSize,
  309. NULL
  310. );
  311. return(NtStatusToClusnetError(status));
  312. } // ClusnetEnableShutdownOnClose
  313. DWORD
  314. ClusnetInitialize(
  315. IN HANDLE ControlChannel,
  316. IN CL_NODE_ID LocalNodeId,
  317. IN ULONG MaxNodes,
  318. IN CLUSNET_NODE_UP_ROUTINE NodeUpRoutine,
  319. IN CLUSNET_NODE_DOWN_ROUTINE NodeDownRoutine,
  320. IN CLUSNET_CHECK_QUORUM_ROUTINE CheckQuorumRoutine,
  321. IN CLUSNET_HOLD_IO_ROUTINE HoldIoRoutine,
  322. IN CLUSNET_RESUME_IO_ROUTINE ResumeIoRoutine,
  323. IN CLUSNET_HALT_ROUTINE HaltRoutine
  324. )
  325. /*++
  326. Routine Description:
  327. Arguments:
  328. ControlChannel - An open handle to the Cluster Network control device.
  329. Return Value:
  330. ERROR_SUCCESS if the operation was successful.
  331. A Windows error code otherwise.
  332. --*/
  333. {
  334. NTSTATUS status;
  335. CLUSNET_INITIALIZE_REQUEST request;
  336. DWORD requestSize = sizeof(request);
  337. DWORD responseSize = 0;
  338. request.LocalNodeId = LocalNodeId;
  339. request.MaxNodes = MaxNodes;
  340. status = DoIoctl(
  341. ControlChannel,
  342. IOCTL_CLUSNET_INITIALIZE,
  343. &request,
  344. requestSize,
  345. NULL,
  346. &responseSize,
  347. NULL
  348. );
  349. return(NtStatusToClusnetError(status));
  350. } // ClusnetInitialize
  351. DWORD
  352. ClusnetShutdown(
  353. IN HANDLE ControlChannel
  354. )
  355. /*++
  356. Routine Description:
  357. Arguments:
  358. ControlChannel - An open handle to the Cluster Network control device.
  359. Return Value:
  360. ERROR_SUCCESS if the operation was successful.
  361. A Windows error code otherwise.
  362. --*/
  363. {
  364. NTSTATUS status;
  365. DWORD requestSize = 0;
  366. DWORD responseSize = 0;
  367. status = DoIoctl(
  368. ControlChannel,
  369. IOCTL_CLUSNET_SHUTDOWN,
  370. NULL,
  371. requestSize,
  372. NULL,
  373. &responseSize,
  374. NULL
  375. );
  376. return(NtStatusToClusnetError(status));
  377. } // ClusnetShutdown
  378. DWORD
  379. ClusnetRegisterNode(
  380. IN HANDLE ControlChannel,
  381. IN CL_NODE_ID NodeId
  382. )
  383. /*++
  384. Routine Description:
  385. Arguments:
  386. ControlChannel - An open handle to the Cluster Network control device.
  387. Return Value:
  388. ERROR_SUCCESS if the operation was successful.
  389. A Windows error code otherwise.
  390. --*/
  391. {
  392. NTSTATUS status;
  393. CX_NODE_REG_REQUEST request;
  394. DWORD requestSize = sizeof(request);
  395. DWORD responseSize = 0;
  396. request.Id = NodeId;
  397. status = DoIoctl(
  398. ControlChannel,
  399. IOCTL_CX_REGISTER_NODE,
  400. &request,
  401. requestSize,
  402. NULL,
  403. &responseSize,
  404. NULL
  405. );
  406. return(NtStatusToClusnetError(status));
  407. } // ClusnetRegisterNode
  408. DWORD
  409. ClusnetDeregisterNode(
  410. IN HANDLE ControlChannel,
  411. IN CL_NODE_ID NodeId
  412. )
  413. /*++
  414. Routine Description:
  415. Arguments:
  416. ControlChannel - An open handle to the Cluster Network control device.
  417. Return Value:
  418. ERROR_SUCCESS if the operation was successful.
  419. A Windows error code otherwise.
  420. --*/
  421. {
  422. NTSTATUS status;
  423. CX_NODE_DEREG_REQUEST request;
  424. DWORD requestSize = sizeof(request);
  425. DWORD responseSize = 0;
  426. request.Id = NodeId;
  427. status = DoIoctl(
  428. ControlChannel,
  429. IOCTL_CX_DEREGISTER_NODE,
  430. &request,
  431. requestSize,
  432. NULL,
  433. &responseSize,
  434. NULL
  435. );
  436. return(NtStatusToClusnetError(status));
  437. } // ClusnetDeregisterNode
  438. DWORD
  439. ClusnetRegisterNetwork(
  440. IN HANDLE ControlChannel,
  441. IN CL_NETWORK_ID NetworkId,
  442. IN ULONG Priority,
  443. IN BOOLEAN Restricted
  444. )
  445. /*++
  446. Routine Description:
  447. Arguments:
  448. ControlChannel - An open handle to the Cluster Network control device.
  449. Return Value:
  450. ERROR_SUCCESS if the operation was successful.
  451. A Windows error code otherwise.
  452. --*/
  453. {
  454. NTSTATUS status;
  455. CX_NETWORK_REG_REQUEST request;
  456. DWORD requestSize = sizeof(request);
  457. DWORD responseSize = 0;
  458. request.Id = NetworkId;
  459. request.Priority = Priority;
  460. request.Restricted = Restricted;
  461. status = DoIoctl(
  462. ControlChannel,
  463. IOCTL_CX_REGISTER_NETWORK,
  464. &request,
  465. requestSize,
  466. NULL,
  467. &responseSize,
  468. NULL
  469. );
  470. return(NtStatusToClusnetError(status));
  471. } // ClusnetRegisterNetwork
  472. DWORD
  473. ClusnetDeregisterNetwork(
  474. IN HANDLE ControlChannel,
  475. IN CL_NETWORK_ID NetworkId
  476. )
  477. /*++
  478. Routine Description:
  479. Arguments:
  480. ControlChannel - An open handle to the Cluster Network control device.
  481. Return Value:
  482. ERROR_SUCCESS if the operation was successful.
  483. A Windows error code otherwise.
  484. --*/
  485. {
  486. NTSTATUS status;
  487. CX_NETWORK_DEREG_REQUEST request;
  488. DWORD requestSize = sizeof(request);
  489. DWORD responseSize = 0;
  490. request.Id = NetworkId;
  491. status = DoIoctl(
  492. ControlChannel,
  493. IOCTL_CX_DEREGISTER_NETWORK,
  494. &request,
  495. requestSize,
  496. NULL,
  497. &responseSize,
  498. NULL
  499. );
  500. return(NtStatusToClusnetError(status));
  501. } // ClusnetDeregisterNetwork
  502. DWORD
  503. ClusnetRegisterInterface(
  504. IN HANDLE ControlChannel,
  505. IN CL_NODE_ID NodeId,
  506. IN CL_NETWORK_ID NetworkId,
  507. IN ULONG Priority,
  508. IN PWSTR AdapterId,
  509. IN ULONG AdapterIdLength,
  510. IN PVOID TdiAddress,
  511. IN ULONG TdiAddressLength,
  512. OUT PULONG MediaStatus
  513. )
  514. /*++
  515. Routine Description:
  516. Registers a node's interface on a network.
  517. Arguments:
  518. ControlChannel - An open handle to the Cluster Network control device.
  519. NodeId - The ID of the node for which to register the interface.
  520. NetworkId - The ID of the network for which to register the interface.
  521. Priority - The priority value assigned to the interface. If a value of
  522. zero is specified, the interface will inherit its priority
  523. from the network.
  524. AdapterId - ID of adapter associated with interface
  525. AdapterIdLength - Length of buffer holding adapter ID, not including
  526. terminating UNICODE_NULL character
  527. TdiAddress - A pointer to a TDI TRANSPORT_ADDRESS structure containing
  528. the transport address of the interface.
  529. TdiAddressLength - The length, in bytes, of the TdiAddress buffer.
  530. MediaStatus - returned current status of media (e.g. cable disconnected)
  531. Return Value:
  532. ERROR_SUCCESS if the operation was successful.
  533. A Windows error code otherwise.
  534. --*/
  535. {
  536. NTSTATUS status;
  537. PCX_INTERFACE_REG_REQUEST request;
  538. DWORD requestSize;
  539. CX_INTERFACE_REG_RESPONSE response;
  540. DWORD responseSize
  541. = sizeof(CX_INTERFACE_REG_RESPONSE);
  542. DWORD adapterIdOffset;
  543. // calculate the size of the request structure without the adapter
  544. // id string.
  545. requestSize = FIELD_OFFSET(CX_INTERFACE_REG_REQUEST, TdiAddress) +
  546. TdiAddressLength;
  547. // round request to type alignment for adapter id string
  548. requestSize = ROUND_UP_COUNT(requestSize, TYPE_ALIGNMENT(PWSTR));
  549. // add buffer for interface name. null-terminate to be safe.
  550. if (AdapterId == NULL) {
  551. AdapterIdLength = 0;
  552. }
  553. adapterIdOffset = requestSize;
  554. requestSize += AdapterIdLength + sizeof(UNICODE_NULL);
  555. if (requestSize < sizeof(CX_INTERFACE_REG_REQUEST)) {
  556. requestSize = sizeof(CX_INTERFACE_REG_REQUEST);
  557. }
  558. request = LocalAlloc(LMEM_FIXED, requestSize);
  559. if (request == NULL) {
  560. return(ERROR_NOT_ENOUGH_MEMORY);
  561. }
  562. ZeroMemory(request, requestSize);
  563. request->NodeId = NodeId;
  564. request->NetworkId = NetworkId;
  565. request->Priority = Priority;
  566. request->TdiAddressLength = TdiAddressLength;
  567. MoveMemory(
  568. &(request->TdiAddress[0]),
  569. TdiAddress,
  570. TdiAddressLength
  571. );
  572. request->AdapterIdLength = AdapterIdLength;
  573. request->AdapterIdOffset = adapterIdOffset;
  574. if (AdapterId != NULL) {
  575. CopyMemory(
  576. (PUWSTR)((PUCHAR)request + adapterIdOffset),
  577. AdapterId,
  578. AdapterIdLength
  579. );
  580. }
  581. status = DoIoctl(
  582. ControlChannel,
  583. IOCTL_CX_REGISTER_INTERFACE,
  584. request,
  585. requestSize,
  586. &response,
  587. &responseSize,
  588. NULL
  589. );
  590. LocalFree(request);
  591. if (MediaStatus != NULL) {
  592. *MediaStatus = response.MediaStatus;
  593. }
  594. return(NtStatusToClusnetError(status));
  595. } // ClusnetRegisterInterface
  596. DWORD
  597. ClusnetDeregisterInterface(
  598. IN HANDLE ControlChannel,
  599. IN CL_NODE_ID NodeId,
  600. IN CL_NETWORK_ID NetworkId
  601. )
  602. /*++
  603. Routine Description:
  604. Arguments:
  605. ControlChannel - An open handle to the Cluster Network control device.
  606. Return Value:
  607. ERROR_SUCCESS if the operation was successful.
  608. A Windows error code otherwise.
  609. --*/
  610. {
  611. NTSTATUS status;
  612. CX_INTERFACE_DEREG_REQUEST request;
  613. DWORD requestSize = sizeof(request);
  614. DWORD responseSize = 0;
  615. request.NodeId = NodeId;
  616. request.NetworkId = NetworkId;
  617. status = DoIoctl(
  618. ControlChannel,
  619. IOCTL_CX_DEREGISTER_INTERFACE,
  620. &request,
  621. requestSize,
  622. NULL,
  623. &responseSize,
  624. NULL
  625. );
  626. return(NtStatusToClusnetError(status));
  627. } // ClusnetDeregisterInterface
  628. DWORD
  629. ClusnetOnlineNodeComm(
  630. IN HANDLE ControlChannel,
  631. IN CL_NODE_ID NodeId
  632. )
  633. /*++
  634. Routine Description:
  635. Enables communication to the specified node.
  636. Arguments:
  637. ControlChannel - An open control channel handle to the Cluster Network
  638. driver.
  639. NodeId - The ID of the node to which to enable communication.
  640. Return Value:
  641. ERROR_SUCCESS if the operation was successful.
  642. A Windows error code otherwise.
  643. --*/
  644. {
  645. NTSTATUS status;
  646. CX_ONLINE_NODE_COMM_REQUEST request;
  647. DWORD requestSize = sizeof(request);
  648. DWORD responseSize = 0;
  649. request.Id = NodeId;
  650. status = DoIoctl(
  651. ControlChannel,
  652. IOCTL_CX_ONLINE_NODE_COMM,
  653. &request,
  654. requestSize,
  655. NULL,
  656. &responseSize,
  657. NULL
  658. );
  659. return(NtStatusToClusnetError(status));
  660. } // ClusnetOnlineNodeCommunication
  661. DWORD
  662. ClusnetOfflineNodeComm(
  663. IN HANDLE ControlChannel,
  664. IN CL_NODE_ID NodeId
  665. )
  666. /*++
  667. Routine Description:
  668. Disable communication to the specified node.
  669. Arguments:
  670. ControlChannel - An open control channel handle to the Cluster Network
  671. driver.
  672. NodeId - The ID of the node to which to disable communication.
  673. Return Value:
  674. ERROR_SUCCESS if the operation was successful.
  675. A Windows error code otherwise.
  676. --*/
  677. {
  678. NTSTATUS status;
  679. CX_OFFLINE_NODE_COMM_REQUEST request;
  680. DWORD requestSize = sizeof(request);
  681. DWORD responseSize = 0;
  682. request.Id = NodeId;
  683. status = DoIoctl(
  684. ControlChannel,
  685. IOCTL_CX_OFFLINE_NODE_COMM,
  686. &request,
  687. requestSize,
  688. NULL,
  689. &responseSize,
  690. NULL
  691. );
  692. return(NtStatusToClusnetError(status));
  693. } // ClusnetOfflineNodeCommunication
  694. DWORD
  695. ClusnetOnlineNetwork(
  696. IN HANDLE ControlChannel,
  697. IN CL_NETWORK_ID NetworkId,
  698. IN PWCHAR TdiProviderName,
  699. IN PVOID TdiBindAddress,
  700. IN ULONG TdiBindAddressLength,
  701. IN LPWSTR AdapterName,
  702. OUT PVOID TdiBindAddressInfo,
  703. IN PULONG TdiBindAddressInfoLength
  704. )
  705. /*++
  706. Routine Description:
  707. Brings a cluster network online using the specified TDI transport
  708. provider and local TDI transport address.
  709. Arguments:
  710. ControlChannel - An open handle to the Cluster Network control device.
  711. NetworkId - The ID of the network to bring online.
  712. TdiProviderName - The name of the transport provider device that
  713. this network should open (e.g. \Device\Udp).
  714. TdiAddress - A pointer to a TDI TRANSPORT_ADDRESS structure containing
  715. the transport address of the local interface to which
  716. the network should be bound.
  717. TdiAddressLength - The length, in bytes, of the TdiAddress buffer.
  718. AdapterName - name of the adapter on which this network is associated
  719. TdiBindAddressInfo - A pointer to a TDI_ADDRESS_INFO structure. On output,
  720. this structure contains the actual address that
  721. the provider opened.
  722. TdiBindAddressInfoLength - On input, a pointer to the size, in bytes,
  723. of the TdiBindAddressInfo parameter. On
  724. output, the variable is updated to the
  725. amount of date returned in the
  726. TdiBindAddressInfo structure.
  727. Return Value:
  728. ERROR_SUCCESS if the operation was successful.
  729. A Windows error code otherwise.
  730. --*/
  731. {
  732. NTSTATUS status;
  733. PCX_ONLINE_NETWORK_REQUEST request;
  734. DWORD requestSize;
  735. PVOID response;
  736. ULONG tdiProviderNameLength;
  737. ULONG adapterNameLength;
  738. tdiProviderNameLength = (wcslen(TdiProviderName) + 1) * sizeof(WCHAR);
  739. adapterNameLength = (wcslen(AdapterName) + 1) * sizeof(WCHAR);
  740. //
  741. // The request size is based on the size and required alignment
  742. // of each field of data following the structure.
  743. //
  744. requestSize = sizeof(CX_ONLINE_NETWORK_REQUEST);
  745. // Provider Name
  746. requestSize = ROUND_UP_COUNT(requestSize, TYPE_ALIGNMENT(PWSTR))
  747. + tdiProviderNameLength;
  748. // Bind Address
  749. requestSize = ROUND_UP_COUNT(requestSize, TYPE_ALIGNMENT(PWSTR))
  750. + TdiBindAddressLength;
  751. // Adapter Name
  752. requestSize = ROUND_UP_COUNT(requestSize, TYPE_ALIGNMENT(PWSTR))
  753. + adapterNameLength;
  754. request = LocalAlloc(LMEM_FIXED, requestSize);
  755. if (request == NULL) {
  756. return(ERROR_NOT_ENOUGH_MEMORY);
  757. }
  758. request->Id = NetworkId;
  759. request->TdiProviderNameLength = tdiProviderNameLength;
  760. request->TdiProviderNameOffset =
  761. ROUND_UP_COUNT(sizeof(CX_ONLINE_NETWORK_REQUEST),
  762. TYPE_ALIGNMENT(PWSTR));
  763. MoveMemory(
  764. (((PUCHAR) request) + request->TdiProviderNameOffset),
  765. TdiProviderName,
  766. tdiProviderNameLength
  767. );
  768. request->TdiBindAddressLength = TdiBindAddressLength;
  769. request->TdiBindAddressOffset =
  770. ROUND_UP_COUNT((request->TdiProviderNameOffset +
  771. tdiProviderNameLength),
  772. TYPE_ALIGNMENT(TRANSPORT_ADDRESS));
  773. MoveMemory(
  774. (((PUCHAR) request) + request->TdiBindAddressOffset),
  775. TdiBindAddress,
  776. TdiBindAddressLength
  777. );
  778. request->AdapterNameLength = adapterNameLength;
  779. request->AdapterNameOffset =
  780. ROUND_UP_COUNT((request->TdiBindAddressOffset +
  781. TdiBindAddressLength),
  782. TYPE_ALIGNMENT(PWSTR));
  783. MoveMemory(
  784. (((PUCHAR) request) + request->AdapterNameOffset),
  785. AdapterName,
  786. adapterNameLength
  787. );
  788. status = DoIoctl(
  789. ControlChannel,
  790. IOCTL_CX_ONLINE_NETWORK,
  791. request,
  792. requestSize,
  793. TdiBindAddressInfo,
  794. TdiBindAddressInfoLength,
  795. NULL
  796. );
  797. LocalFree(request);
  798. return(NtStatusToClusnetError(status));
  799. } // ClusnetOnlineNetwork
  800. DWORD
  801. ClusnetOfflineNetwork(
  802. IN HANDLE ControlChannel,
  803. IN CL_NETWORK_ID NetworkId
  804. )
  805. /*++
  806. Routine Description:
  807. Arguments:
  808. ControlChannel - An open handle to the Cluster Network control device.
  809. Return Value:
  810. ERROR_SUCCESS if the operation was successful.
  811. A Windows error code otherwise.
  812. --*/
  813. {
  814. NTSTATUS status;
  815. CX_OFFLINE_NETWORK_REQUEST request;
  816. DWORD requestSize = sizeof(request);
  817. DWORD responseSize = 0;
  818. request.Id = NetworkId;
  819. status = DoIoctl(
  820. ControlChannel,
  821. IOCTL_CX_OFFLINE_NETWORK,
  822. &request,
  823. requestSize,
  824. NULL,
  825. &responseSize,
  826. NULL
  827. );
  828. return(NtStatusToClusnetError(status));
  829. } // ClusnetOfflineNetwork
  830. DWORD
  831. ClusnetSetNetworkRestriction(
  832. IN HANDLE ControlChannel,
  833. IN CL_NETWORK_ID NetworkId,
  834. IN BOOLEAN Restricted,
  835. IN ULONG NewPriority
  836. )
  837. /*++
  838. Routine Description:
  839. Arguments:
  840. ControlChannel - An open handle to the Cluster Network control device.
  841. Return Value:
  842. ERROR_SUCCESS if the operation was successful.
  843. A Windows error code otherwise.
  844. --*/
  845. {
  846. NTSTATUS status;
  847. CX_SET_NETWORK_RESTRICTION_REQUEST request;
  848. DWORD responseSize = 0;
  849. request.Id = NetworkId;
  850. request.Restricted = Restricted;
  851. request.NewPriority = NewPriority;
  852. status = DoIoctl(
  853. ControlChannel,
  854. IOCTL_CX_SET_NETWORK_RESTRICTION,
  855. &request,
  856. sizeof(CX_SET_NETWORK_RESTRICTION_REQUEST),
  857. NULL,
  858. &responseSize,
  859. NULL
  860. );
  861. return(NtStatusToClusnetError(status));
  862. } // ClusnetSetNetworkRestriction
  863. DWORD
  864. ClusnetGetNetworkPriority(
  865. IN HANDLE ControlChannel,
  866. IN CL_NETWORK_ID NetworkId,
  867. OUT PULONG Priority
  868. )
  869. /*++
  870. Routine Description:
  871. Arguments:
  872. ControlChannel - An open handle to the Cluster Network control device.
  873. Return Value:
  874. ERROR_SUCCESS if the operation was successful.
  875. A Windows error code otherwise.
  876. --*/
  877. {
  878. NTSTATUS status;
  879. PCX_GET_NETWORK_PRIORITY_REQUEST request;
  880. PCX_GET_NETWORK_PRIORITY_RESPONSE response;
  881. DWORD requestSize;
  882. DWORD responseSize;
  883. requestSize = sizeof(CX_GET_NETWORK_PRIORITY_REQUEST);
  884. responseSize = sizeof(CX_GET_NETWORK_PRIORITY_RESPONSE);
  885. if (requestSize > responseSize) {
  886. request = LocalAlloc(LMEM_FIXED, requestSize);
  887. response = (PCX_GET_NETWORK_PRIORITY_RESPONSE) request;
  888. }
  889. else {
  890. response = LocalAlloc(LMEM_FIXED, responseSize);
  891. request = (PCX_GET_NETWORK_PRIORITY_REQUEST) response;
  892. }
  893. if (request == NULL) {
  894. return(ERROR_NOT_ENOUGH_MEMORY);
  895. }
  896. request->Id = NetworkId;
  897. status = DoIoctl(
  898. ControlChannel,
  899. IOCTL_CX_GET_NETWORK_PRIORITY,
  900. request,
  901. requestSize,
  902. response,
  903. &responseSize,
  904. NULL
  905. );
  906. if (status == STATUS_SUCCESS) {
  907. if (responseSize != sizeof(CX_GET_NETWORK_PRIORITY_RESPONSE)) {
  908. status = STATUS_UNSUCCESSFUL;
  909. }
  910. else {
  911. *Priority = response->Priority;
  912. }
  913. }
  914. LocalFree(request);
  915. return(NtStatusToClusnetError(status));
  916. } // ClusnetGetNetworkPriority
  917. DWORD
  918. ClusnetSetNetworkPriority(
  919. IN HANDLE ControlChannel,
  920. IN CL_NETWORK_ID NetworkId,
  921. IN ULONG Priority
  922. )
  923. /*++
  924. Routine Description:
  925. ControlChannel - An open handle to the Cluster Network control device.
  926. Arguments:
  927. Return Value:
  928. ERROR_SUCCESS if the operation was successful.
  929. A Windows error code otherwise.
  930. --*/
  931. {
  932. NTSTATUS status;
  933. CX_SET_NETWORK_PRIORITY_REQUEST request;
  934. DWORD responseSize = 0;
  935. request.Id = NetworkId;
  936. request.Priority = Priority;
  937. status = DoIoctl(
  938. ControlChannel,
  939. IOCTL_CX_SET_NETWORK_PRIORITY,
  940. &request,
  941. sizeof(CX_SET_NETWORK_PRIORITY_REQUEST),
  942. NULL,
  943. &responseSize,
  944. NULL
  945. );
  946. return(NtStatusToClusnetError(status));
  947. } // ClusnetSetNetworkPriority
  948. DWORD
  949. ClusnetGetInterfacePriority(
  950. IN HANDLE ControlChannel,
  951. IN CL_NODE_ID NodeId,
  952. IN CL_NETWORK_ID NetworkId,
  953. OUT PULONG InterfacePriority,
  954. OUT PULONG NetworkPriority
  955. )
  956. /*++
  957. Routine Description:
  958. Arguments:
  959. ControlChannel - An open handle to the Cluster Network control device.
  960. Return Value:
  961. ERROR_SUCCESS if the operation was successful.
  962. A Windows error code otherwise.
  963. --*/
  964. {
  965. NTSTATUS status;
  966. PCX_GET_INTERFACE_PRIORITY_REQUEST request;
  967. PCX_GET_INTERFACE_PRIORITY_RESPONSE response;
  968. DWORD requestSize;
  969. DWORD responseSize;
  970. requestSize = sizeof(CX_GET_INTERFACE_PRIORITY_REQUEST);
  971. responseSize = sizeof(CX_GET_INTERFACE_PRIORITY_RESPONSE);
  972. if (requestSize > responseSize) {
  973. request = LocalAlloc(LMEM_FIXED, requestSize);
  974. response = (PCX_GET_INTERFACE_PRIORITY_RESPONSE) request;
  975. }
  976. else {
  977. response = LocalAlloc(LMEM_FIXED, responseSize);
  978. request = (PCX_GET_INTERFACE_PRIORITY_REQUEST) response;
  979. }
  980. if (request == NULL) {
  981. return(ERROR_NOT_ENOUGH_MEMORY);
  982. }
  983. request->NodeId = NodeId;
  984. request->NetworkId = NetworkId;
  985. status = DoIoctl(
  986. ControlChannel,
  987. IOCTL_CX_GET_INTERFACE_PRIORITY,
  988. request,
  989. requestSize,
  990. response,
  991. &responseSize,
  992. NULL
  993. );
  994. if (status == STATUS_SUCCESS) {
  995. if (responseSize != sizeof(CX_GET_INTERFACE_PRIORITY_RESPONSE)) {
  996. status = STATUS_UNSUCCESSFUL;
  997. }
  998. else {
  999. *InterfacePriority = response->InterfacePriority;
  1000. *NetworkPriority = response->NetworkPriority;
  1001. }
  1002. }
  1003. LocalFree(request);
  1004. return(NtStatusToClusnetError(status));
  1005. } // ClusnetGetInterfacePriority
  1006. DWORD
  1007. ClusnetSetInterfacePriority(
  1008. IN HANDLE ControlChannel,
  1009. IN CL_NODE_ID NodeId,
  1010. IN CL_NETWORK_ID NetworkId,
  1011. IN ULONG Priority
  1012. )
  1013. /*++
  1014. Routine Description:
  1015. Arguments:
  1016. ControlChannel - An open handle to the Cluster Network control device.
  1017. Return Value:
  1018. ERROR_SUCCESS if the operation was successful.
  1019. A Windows error code otherwise.
  1020. --*/
  1021. {
  1022. NTSTATUS status;
  1023. CX_SET_INTERFACE_PRIORITY_REQUEST request;
  1024. DWORD responseSize = 0;
  1025. request.NodeId = NodeId;
  1026. request.NetworkId = NetworkId;
  1027. request.Priority = Priority;
  1028. status = DoIoctl(
  1029. ControlChannel,
  1030. IOCTL_CX_SET_INTERFACE_PRIORITY,
  1031. &request,
  1032. sizeof(CX_SET_INTERFACE_PRIORITY_REQUEST),
  1033. NULL,
  1034. &responseSize,
  1035. NULL
  1036. );
  1037. return(NtStatusToClusnetError(status));
  1038. } // ClusnetGetInterfacePriority
  1039. DWORD
  1040. ClusnetGetNodeCommState(
  1041. IN HANDLE ControlChannel,
  1042. IN CL_NODE_ID NodeId,
  1043. OUT PCLUSNET_NODE_COMM_STATE State
  1044. )
  1045. /*++
  1046. Routine Description:
  1047. Arguments:
  1048. ControlChannel - An open handle to the Cluster Network control device.
  1049. Return Value:
  1050. ERROR_SUCCESS if the operation was successful.
  1051. A Windows error code otherwise.
  1052. --*/
  1053. {
  1054. NTSTATUS status;
  1055. PCX_GET_NODE_STATE_REQUEST request;
  1056. PCX_GET_NODE_STATE_RESPONSE response;
  1057. DWORD requestSize;
  1058. DWORD responseSize;
  1059. requestSize = sizeof(CX_GET_NODE_STATE_REQUEST);
  1060. responseSize = sizeof(CX_GET_NODE_STATE_RESPONSE);
  1061. if (requestSize > responseSize) {
  1062. request = LocalAlloc(LMEM_FIXED, requestSize);
  1063. response = (PCX_GET_NODE_STATE_RESPONSE) request;
  1064. }
  1065. else {
  1066. response = LocalAlloc(LMEM_FIXED, responseSize);
  1067. request = (PCX_GET_NODE_STATE_REQUEST) response;
  1068. }
  1069. if (request == NULL) {
  1070. return(ERROR_NOT_ENOUGH_MEMORY);
  1071. }
  1072. request->Id = NodeId;
  1073. status = DoIoctl(
  1074. ControlChannel,
  1075. IOCTL_CX_GET_NODE_STATE,
  1076. request,
  1077. requestSize,
  1078. response,
  1079. &responseSize,
  1080. NULL
  1081. );
  1082. if (status == STATUS_SUCCESS) {
  1083. if (responseSize != sizeof(CX_GET_NODE_STATE_RESPONSE)) {
  1084. status = STATUS_UNSUCCESSFUL;
  1085. }
  1086. else {
  1087. *State = response->State;
  1088. }
  1089. }
  1090. LocalFree(request);
  1091. return(NtStatusToClusnetError(status));
  1092. } // ClusnetGetNodeState
  1093. DWORD
  1094. ClusnetGetNetworkState(
  1095. IN HANDLE ControlChannel,
  1096. IN CL_NETWORK_ID NetworkId,
  1097. OUT PCLUSNET_NETWORK_STATE State
  1098. )
  1099. /*++
  1100. Routine Description:
  1101. Arguments:
  1102. ControlChannel - An open handle to the Cluster Network control device.
  1103. Return Value:
  1104. ERROR_SUCCESS if the operation was successful.
  1105. A Windows error code otherwise.
  1106. --*/
  1107. {
  1108. NTSTATUS status;
  1109. PCX_GET_NETWORK_STATE_REQUEST request;
  1110. PCX_GET_NETWORK_STATE_RESPONSE response;
  1111. DWORD requestSize;
  1112. DWORD responseSize;
  1113. requestSize = sizeof(CX_GET_NETWORK_STATE_REQUEST);
  1114. responseSize = sizeof(CX_GET_NETWORK_STATE_RESPONSE);
  1115. if (requestSize > responseSize) {
  1116. request = LocalAlloc(LMEM_FIXED, requestSize);
  1117. response = (PCX_GET_NETWORK_STATE_RESPONSE) request;
  1118. }
  1119. else {
  1120. response = LocalAlloc(LMEM_FIXED, responseSize);
  1121. request = (PCX_GET_NETWORK_STATE_REQUEST) response;
  1122. }
  1123. if (request == NULL) {
  1124. return(ERROR_NOT_ENOUGH_MEMORY);
  1125. }
  1126. request->Id = NetworkId;
  1127. status = DoIoctl(
  1128. ControlChannel,
  1129. IOCTL_CX_GET_NETWORK_STATE,
  1130. request,
  1131. requestSize,
  1132. response,
  1133. &responseSize,
  1134. NULL
  1135. );
  1136. if (status == STATUS_SUCCESS) {
  1137. if (responseSize != sizeof(CX_GET_NETWORK_STATE_RESPONSE)) {
  1138. status = STATUS_UNSUCCESSFUL;
  1139. }
  1140. else {
  1141. *State = response->State;
  1142. }
  1143. }
  1144. LocalFree(request);
  1145. return(NtStatusToClusnetError(status));
  1146. } // ClusnetGetNetworkState
  1147. DWORD
  1148. ClusnetGetInterfaceState(
  1149. IN HANDLE ControlChannel,
  1150. IN CL_NODE_ID NodeId,
  1151. IN CL_NETWORK_ID NetworkId,
  1152. OUT PCLUSNET_INTERFACE_STATE State
  1153. )
  1154. /*++
  1155. Routine Description:
  1156. Arguments:
  1157. ControlChannel - An open handle to the Cluster Network control device.
  1158. Return Value:
  1159. ERROR_SUCCESS if the operation was successful.
  1160. A Windows error code otherwise.
  1161. --*/
  1162. {
  1163. NTSTATUS status;
  1164. PCX_GET_INTERFACE_STATE_REQUEST request;
  1165. PCX_GET_INTERFACE_STATE_RESPONSE response;
  1166. DWORD requestSize;
  1167. DWORD responseSize;
  1168. requestSize = sizeof(CX_GET_INTERFACE_STATE_REQUEST);
  1169. responseSize = sizeof(CX_GET_INTERFACE_STATE_RESPONSE);
  1170. if (requestSize > responseSize) {
  1171. request = LocalAlloc(LMEM_FIXED, requestSize);
  1172. response = (PCX_GET_INTERFACE_STATE_RESPONSE) request;
  1173. }
  1174. else {
  1175. response = LocalAlloc(LMEM_FIXED, responseSize);
  1176. request = (PCX_GET_INTERFACE_STATE_REQUEST) response;
  1177. }
  1178. if (request == NULL) {
  1179. return(ERROR_NOT_ENOUGH_MEMORY);
  1180. }
  1181. request->NodeId = NodeId;
  1182. request->NetworkId = NetworkId;
  1183. status = DoIoctl(
  1184. ControlChannel,
  1185. IOCTL_CX_GET_INTERFACE_STATE,
  1186. request,
  1187. requestSize,
  1188. response,
  1189. &responseSize,
  1190. NULL
  1191. );
  1192. if (status == STATUS_SUCCESS) {
  1193. if (responseSize != sizeof(CX_GET_INTERFACE_STATE_RESPONSE)) {
  1194. status = STATUS_UNSUCCESSFUL;
  1195. }
  1196. else {
  1197. *State = response->State;
  1198. }
  1199. }
  1200. LocalFree(request);
  1201. return(NtStatusToClusnetError(status));
  1202. } // ClusnetGetInterfaceState
  1203. #ifdef MM_IN_CLUSNSET
  1204. DWORD
  1205. ClusnetFormCluster(
  1206. IN HANDLE ControlChannel,
  1207. IN ULONG ClockPeriod,
  1208. IN ULONG SendHBRate,
  1209. IN ULONG RecvHBRate
  1210. )
  1211. /*++
  1212. Routine Description:
  1213. Arguments:
  1214. ControlChannel - An open handle to the Cluster Network control device.
  1215. Return Value:
  1216. ERROR_SUCCESS if the operation was successful.
  1217. A Windows error code otherwise.
  1218. --*/
  1219. {
  1220. NTSTATUS status;
  1221. CMM_FORM_CLUSTER_REQUEST request;
  1222. DWORD requestSize = sizeof(request);
  1223. DWORD responseSize = 0;
  1224. request.ClockPeriod = ClockPeriod;
  1225. request.SendHBRate = SendHBRate;
  1226. request.RecvHBRate = RecvHBRate;
  1227. status = DoIoctl(
  1228. ControlChannel,
  1229. IOCTL_CMM_FORM_CLUSTER,
  1230. &request,
  1231. requestSize,
  1232. NULL,
  1233. &responseSize,
  1234. NULL
  1235. );
  1236. return(NtStatusToClusnetError(status));
  1237. } // ClusnetFormCluster
  1238. DWORD
  1239. ClusnetJoinCluster(
  1240. IN HANDLE ControlChannel,
  1241. IN CL_NODE_ID JoiningNodeId,
  1242. IN CLUSNET_JOIN_PHASE Phase,
  1243. IN ULONG JoinTimeout,
  1244. IN OUT PVOID * MessageToSend,
  1245. OUT PULONG MessageLength,
  1246. OUT PULONG DestNodeMask
  1247. )
  1248. /*++
  1249. Routine Description:
  1250. Arguments:
  1251. ControlChannel - An open handle to the Cluster Network control device.
  1252. Return Value:
  1253. ERROR_SUCCESS if the operation was successful.
  1254. A Windows error code otherwise.
  1255. --*/
  1256. {
  1257. NTSTATUS status;
  1258. CMM_JOIN_CLUSTER_REQUEST request;
  1259. DWORD requestSize = sizeof(request);
  1260. PCMM_JOIN_CLUSTER_RESPONSE response;
  1261. ULONG IoctlCode;
  1262. DWORD responseSize;
  1263. //
  1264. // Parse the input parameters
  1265. //
  1266. if ( Phase == ClusnetJoinPhase1 )
  1267. IoctlCode = IOCTL_CMM_JOIN_CLUSTER_PHASE1;
  1268. else if ( Phase == ClusnetJoinPhase2 )
  1269. IoctlCode = IOCTL_CMM_JOIN_CLUSTER_PHASE2;
  1270. else if ( Phase == ClusnetJoinPhase3 )
  1271. IoctlCode = IOCTL_CMM_JOIN_CLUSTER_PHASE3;
  1272. else if ( Phase == ClusnetJoinPhase4 )
  1273. IoctlCode = IOCTL_CMM_JOIN_CLUSTER_PHASE4;
  1274. else if ( Phase == ClusnetJoinPhaseAbort )
  1275. IoctlCode = IOCTL_CMM_JOIN_CLUSTER_ABORT;
  1276. else
  1277. return(ERROR_INVALID_PARAMETER);
  1278. request.JoiningNode = JoiningNodeId;
  1279. request.JoinTimeout = JoinTimeout;
  1280. //
  1281. // allocate space for the response buffer and a message space at the back
  1282. // of the struct. Current RGP message requirements are 80 bytes
  1283. // (sizeof(rgp_msgbuf)).
  1284. //
  1285. responseSize = sizeof(*response) + 200;
  1286. if (*MessageToSend != NULL) {
  1287. //
  1288. // recycle old message buffer
  1289. //
  1290. response = CONTAINING_RECORD(
  1291. *MessageToSend,
  1292. CMM_JOIN_CLUSTER_RESPONSE,
  1293. SendData
  1294. );
  1295. }
  1296. else {
  1297. response = LocalAlloc(LMEM_FIXED, responseSize);
  1298. }
  1299. if ( response == NULL ) {
  1300. return(ERROR_NOT_ENOUGH_MEMORY);
  1301. }
  1302. status = DoIoctl(
  1303. ControlChannel,
  1304. IoctlCode,
  1305. &request,
  1306. requestSize,
  1307. response,
  1308. &responseSize,
  1309. NULL
  1310. );
  1311. if (NT_SUCCESS(status)) {
  1312. *MessageToSend = &(response->SendData[0]);
  1313. *MessageLength = response->SizeOfSendData;
  1314. *DestNodeMask = response->SendNodeMask;
  1315. return(ERROR_SUCCESS);
  1316. }
  1317. LocalFree( response );
  1318. *MessageToSend = NULL;
  1319. return(NtStatusToClusnetError(status));
  1320. } // ClusnetJoinCluster
  1321. VOID
  1322. ClusnetEndJoinCluster(
  1323. IN HANDLE ControlChannel,
  1324. IN PVOID LastSentMessage
  1325. )
  1326. {
  1327. ULONG responseSize = 0;
  1328. PCMM_JOIN_CLUSTER_RESPONSE response;
  1329. if (LastSentMessage != NULL) {
  1330. response = CONTAINING_RECORD(
  1331. LastSentMessage,
  1332. CMM_JOIN_CLUSTER_RESPONSE,
  1333. SendData
  1334. );
  1335. LocalFree(response);
  1336. }
  1337. (VOID) DoIoctl(
  1338. ControlChannel,
  1339. IOCTL_CMM_JOIN_CLUSTER_END,
  1340. NULL,
  1341. 0,
  1342. NULL,
  1343. &responseSize,
  1344. NULL
  1345. );
  1346. return;
  1347. } // ClusnetEndJoinCluster
  1348. DWORD
  1349. ClusnetDeliverJoinMessage(
  1350. IN HANDLE ControlChannel,
  1351. IN PVOID Message,
  1352. IN ULONG MessageLength
  1353. )
  1354. {
  1355. NTSTATUS status;
  1356. DWORD responseSize = 0;
  1357. status = DoIoctl(
  1358. ControlChannel,
  1359. IOCTL_CMM_DELIVER_JOIN_MESSAGE,
  1360. Message,
  1361. MessageLength,
  1362. NULL,
  1363. &responseSize,
  1364. NULL
  1365. );
  1366. return(NtStatusToClusnetError(status));
  1367. } // ClusnetDeliverJoinMessage
  1368. DWORD
  1369. ClusnetLeaveCluster(
  1370. IN HANDLE ControlChannel
  1371. )
  1372. /*++
  1373. Routine Description:
  1374. Arguments:
  1375. ControlChannel - An open handle to the Cluster Network control device.
  1376. Return Value:
  1377. ERROR_SUCCESS if the operation was successful.
  1378. A Windows error code otherwise.
  1379. --*/
  1380. {
  1381. NTSTATUS status;
  1382. DWORD responseSize = 0;
  1383. status = DoIoctl(
  1384. ControlChannel,
  1385. IOCTL_CMM_LEAVE_CLUSTER,
  1386. NULL,
  1387. 0,
  1388. NULL,
  1389. &responseSize,
  1390. NULL
  1391. );
  1392. return(NtStatusToClusnetError(status));
  1393. } // ClusnetLeaveCluster
  1394. DWORD
  1395. ClusnetEvictNode(
  1396. IN HANDLE ControlChannel,
  1397. IN ULONG NodeId
  1398. )
  1399. /*++
  1400. Routine Description:
  1401. Arguments:
  1402. ControlChannel - An open handle to the Cluster Network control device.
  1403. Return Value:
  1404. ERROR_SUCCESS if the operation was successful.
  1405. A Windows error code otherwise.
  1406. --*/
  1407. {
  1408. NTSTATUS status;
  1409. CMM_EJECT_CLUSTER_REQUEST request;
  1410. DWORD requestSize = sizeof(request);
  1411. DWORD responseSize = 0;
  1412. request.Node = NodeId;
  1413. status = DoIoctl(
  1414. ControlChannel,
  1415. IOCTL_CMM_EJECT_CLUSTER,
  1416. &request,
  1417. requestSize,
  1418. NULL,
  1419. &responseSize,
  1420. NULL
  1421. );
  1422. return(NtStatusToClusnetError(status));
  1423. } // ClusnetEvictNode
  1424. #endif // MM_IN_CLUSNSET
  1425. DWORD
  1426. ClusnetGetNodeMembershipState(
  1427. IN HANDLE ControlChannel,
  1428. IN ULONG NodeId,
  1429. OUT CLUSNET_NODE_STATE * State
  1430. )
  1431. /*++
  1432. Routine Description:
  1433. Arguments:
  1434. ControlChannel - An open handle to the Cluster Network control device.
  1435. Return Value:
  1436. ERROR_SUCCESS if the operation was successful.
  1437. A Windows error code otherwise.
  1438. --*/
  1439. {
  1440. NTSTATUS status;
  1441. CX_GET_NODE_MMSTATE_REQUEST request;
  1442. DWORD requestSize = sizeof(request);
  1443. CX_GET_NODE_MMSTATE_RESPONSE response;
  1444. DWORD responseSize = sizeof(response);
  1445. request.Id = NodeId;
  1446. status = DoIoctl(
  1447. ControlChannel,
  1448. IOCTL_CX_GET_NODE_MMSTATE,
  1449. &request,
  1450. requestSize,
  1451. &response,
  1452. &responseSize,
  1453. NULL
  1454. );
  1455. if (status == STATUS_SUCCESS) {
  1456. *State = response.State;
  1457. }
  1458. return(NtStatusToClusnetError(status));
  1459. } // ClusnetGetNodeMembershipState
  1460. DWORD
  1461. ClusnetSetNodeMembershipState(
  1462. IN HANDLE ControlChannel,
  1463. IN ULONG NodeId,
  1464. IN CLUSNET_NODE_STATE State
  1465. )
  1466. /*++
  1467. Routine Description:
  1468. Set the internal node membership state to the indicated value
  1469. Arguments:
  1470. ControlChannel - An open handle to the Cluster Network control device.
  1471. Return Value:
  1472. ERROR_SUCCESS if the operation was successful.
  1473. A Windows error code otherwise.
  1474. --*/
  1475. {
  1476. NTSTATUS status;
  1477. CX_SET_NODE_MMSTATE_REQUEST request;
  1478. DWORD requestSize = sizeof(request);
  1479. DWORD responseSize;
  1480. request.NodeId = NodeId;
  1481. request.State = State;
  1482. status = DoIoctl(
  1483. ControlChannel,
  1484. IOCTL_CX_SET_NODE_MMSTATE,
  1485. &request,
  1486. requestSize,
  1487. NULL,
  1488. &responseSize,
  1489. NULL
  1490. );
  1491. return(NtStatusToClusnetError(status));
  1492. } // ClusnetSetNodeMembershipState
  1493. DWORD
  1494. ClusnetSetEventMask(
  1495. IN HANDLE ControlChannel,
  1496. IN CLUSNET_EVENT_TYPE EventMask
  1497. )
  1498. /*++
  1499. Routine Description:
  1500. Based on the supplied callback pointers, set the mask of events
  1501. generated in kernel mode in which this file handle is interested
  1502. Arguments:
  1503. ControlChannel - An open handle to the Cluster Network control device.
  1504. EventMask - bit mask of interested events
  1505. Return Value:
  1506. ERROR_SUCCESS if the operation was successful.
  1507. A Windows error code otherwise.
  1508. --*/
  1509. {
  1510. NTSTATUS status;
  1511. CLUSNET_SET_EVENT_MASK_REQUEST request;
  1512. DWORD requestSize = sizeof(request);
  1513. DWORD responseSize = 0;
  1514. request.EventMask = EventMask;
  1515. request.KmodeEventCallback = NULL;
  1516. status = DoIoctl(
  1517. ControlChannel,
  1518. IOCTL_CLUSNET_SET_EVENT_MASK,
  1519. &request,
  1520. requestSize,
  1521. NULL,
  1522. &responseSize,
  1523. NULL
  1524. );
  1525. return(NtStatusToClusnetError(status));
  1526. } // ClusnetSetEventMask
  1527. DWORD
  1528. ClusnetGetNextEvent(
  1529. IN HANDLE ControlChannel,
  1530. OUT PCLUSNET_EVENT Event,
  1531. IN LPOVERLAPPED Overlapped OPTIONAL
  1532. )
  1533. /*++
  1534. Routine Description:
  1535. Wait for the next event to be completed.
  1536. Arguments:
  1537. ControlChannel - An open handle to the Cluster Network control device.
  1538. Event - handle to event that is set when IO is complete
  1539. Response - pointer to structure that is filled in when IRP completes
  1540. Return Value:
  1541. ERROR_SUCCESS if the operation was successful.
  1542. A Windows error code otherwise.
  1543. --*/
  1544. {
  1545. NTSTATUS status;
  1546. ULONG ResponseSize = sizeof( CLUSNET_EVENT );
  1547. //
  1548. // if no event passed in, then assume the caller wants to block.
  1549. // we still need an event to block on while waiting...
  1550. //
  1551. status = DoIoctl(
  1552. ControlChannel,
  1553. IOCTL_CLUSNET_GET_NEXT_EVENT,
  1554. NULL,
  1555. 0,
  1556. Event,
  1557. &ResponseSize,
  1558. Overlapped
  1559. );
  1560. return(NtStatusToClusnetError(status));
  1561. } // ClusnetGetNextEvent
  1562. DWORD
  1563. ClusnetHalt(
  1564. IN HANDLE ControlChannel
  1565. )
  1566. /*++
  1567. Routine Description:
  1568. Tell clusnet that we need to halt immediately
  1569. Arguments:
  1570. ControlChannel - An open handle to the Cluster Network control device.
  1571. Return Value:
  1572. ERROR_SUCCESS if the operation was successful.
  1573. A Windows error code otherwise.
  1574. --*/
  1575. {
  1576. NTSTATUS status;
  1577. DWORD responseSize;
  1578. status = DoIoctl(
  1579. ControlChannel,
  1580. IOCTL_CLUSNET_HALT,
  1581. NULL,
  1582. 0,
  1583. NULL,
  1584. &responseSize,
  1585. NULL
  1586. );
  1587. return(NtStatusToClusnetError(status));
  1588. } // ClusnetHalt
  1589. DWORD
  1590. ClusnetSetMemLogging(
  1591. IN HANDLE ControlChannel,
  1592. IN ULONG NumberOfEntries
  1593. )
  1594. /*++
  1595. Routine Description:
  1596. Turn in-memory logging in clusnet on or off.
  1597. Arguments:
  1598. ControlChannel - An open handle to the Cluster Network control device.
  1599. NumberOfEntires - # of entries to allocate for the log. Zero turns off logging
  1600. Return Value:
  1601. ERROR_SUCCESS if the operation was successful.
  1602. A Windows error code otherwise.
  1603. --*/
  1604. {
  1605. NTSTATUS status;
  1606. CLUSNET_SET_MEM_LOGGING_REQUEST request;
  1607. DWORD requestSize = sizeof( request );
  1608. DWORD responseSize;
  1609. request.NumberOfEntries = NumberOfEntries;
  1610. status = DoIoctl(
  1611. ControlChannel,
  1612. IOCTL_CLUSNET_SET_MEMORY_LOGGING,
  1613. &request,
  1614. requestSize,
  1615. NULL,
  1616. &responseSize,
  1617. NULL
  1618. );
  1619. return(NtStatusToClusnetError(status));
  1620. } // ClusnetSetMemLogging
  1621. DWORD
  1622. ClusnetSendPoisonPacket(
  1623. IN HANDLE ControlChannel,
  1624. IN CL_NODE_ID NodeId
  1625. )
  1626. /*++
  1627. Routine Description:
  1628. Send a poison packet to the indicated node
  1629. Arguments:
  1630. ControlChannel - An open handle to the Cluster Network control device.
  1631. Return Value:
  1632. ERROR_SUCCESS if the operation was successful.
  1633. A Windows error code otherwise.
  1634. --*/
  1635. {
  1636. NTSTATUS status;
  1637. CX_SEND_POISON_PKT_REQUEST request;
  1638. DWORD requestSize = sizeof(request);
  1639. DWORD responseSize = 0;
  1640. request.Id = NodeId;
  1641. status = DoIoctl(
  1642. ControlChannel,
  1643. IOCTL_CX_SEND_POISON_PACKET,
  1644. &request,
  1645. requestSize,
  1646. NULL,
  1647. &responseSize,
  1648. NULL
  1649. );
  1650. return(NtStatusToClusnetError(status));
  1651. }
  1652. DWORD
  1653. ClusnetSetOuterscreen(
  1654. IN HANDLE ControlChannel,
  1655. IN ULONG Outerscreen
  1656. )
  1657. /*++
  1658. Routine Description:
  1659. set the cluster member outerscreen
  1660. Arguments:
  1661. ControlChannel - An open handle to the Cluster Network control device.
  1662. Return Value:
  1663. ERROR_SUCCESS if the operation was successful.
  1664. A Windows error code otherwise.
  1665. --*/
  1666. {
  1667. NTSTATUS status;
  1668. CX_SET_OUTERSCREEN_REQUEST request;
  1669. DWORD requestSize = sizeof(request);
  1670. DWORD responseSize = 0;
  1671. request.Outerscreen = Outerscreen;
  1672. status = DoIoctl(
  1673. ControlChannel,
  1674. IOCTL_CX_SET_OUTERSCREEN,
  1675. &request,
  1676. requestSize,
  1677. NULL,
  1678. &responseSize,
  1679. NULL
  1680. );
  1681. return(NtStatusToClusnetError(status));
  1682. }
  1683. DWORD
  1684. ClusnetRegroupFinished(
  1685. IN HANDLE ControlChannel,
  1686. IN ULONG EventEpoch,
  1687. IN ULONG RegroupEpoch
  1688. )
  1689. /*++
  1690. Routine Description:
  1691. inform clusnet that regroup has finished
  1692. Arguments:
  1693. ControlChannel - An open handle to the Cluster Network control device.
  1694. NewEpoch - new event epoch used to detect stale events
  1695. Return Value:
  1696. ERROR_SUCCESS if the operation was successful.
  1697. A Windows error code otherwise.
  1698. --*/
  1699. {
  1700. NTSTATUS status;
  1701. CX_REGROUP_FINISHED_REQUEST request;
  1702. DWORD requestSize = sizeof(request);
  1703. DWORD responseSize = 0;
  1704. request.EventEpoch = EventEpoch;
  1705. request.RegroupEpoch = RegroupEpoch;
  1706. status = DoIoctl(
  1707. ControlChannel,
  1708. IOCTL_CX_REGROUP_FINISHED,
  1709. &request,
  1710. requestSize,
  1711. NULL,
  1712. &responseSize,
  1713. NULL
  1714. );
  1715. return(NtStatusToClusnetError(status));
  1716. }
  1717. DWORD
  1718. ClusnetImportSecurityContexts(
  1719. IN HANDLE ControlChannel,
  1720. IN CL_NODE_ID JoiningNodeId,
  1721. IN PWCHAR PackageName,
  1722. IN ULONG SignatureSize,
  1723. IN PVOID ServerContext,
  1724. IN PVOID ClientContext
  1725. )
  1726. /*++
  1727. Routine Description:
  1728. inform clusnet that regroup has finished
  1729. Arguments:
  1730. ControlChannel - An open handle to the Cluster Network control device.
  1731. NewEpoch - new event epoch used to detect stale events
  1732. Return Value:
  1733. ERROR_SUCCESS if the operation was successful.
  1734. A Windows error code otherwise.
  1735. --*/
  1736. {
  1737. NTSTATUS status;
  1738. CX_IMPORT_SECURITY_CONTEXT_REQUEST request;
  1739. DWORD requestSize = sizeof(request);
  1740. DWORD responseSize = 0;
  1741. request.JoiningNodeId = JoiningNodeId;
  1742. request.PackageName = PackageName;
  1743. request.PackageNameSize = sizeof(WCHAR) * ( wcslen( PackageName ) + 1 );
  1744. request.SignatureSize = SignatureSize;
  1745. request.ServerContext = ServerContext;
  1746. request.ClientContext = ClientContext;
  1747. status = DoIoctl(
  1748. ControlChannel,
  1749. IOCTL_CX_IMPORT_SECURITY_CONTEXTS,
  1750. &request,
  1751. requestSize,
  1752. NULL,
  1753. &responseSize,
  1754. NULL
  1755. );
  1756. return(NtStatusToClusnetError(status));
  1757. }
  1758. DWORD
  1759. ClusnetReserveEndpoint(
  1760. IN HANDLE ControlChannel,
  1761. IN PWSTR EndpointString
  1762. )
  1763. /*++
  1764. Routine Description:
  1765. Tell clusnet to tell TCP/IP to reserve the port number in
  1766. EndpointString.
  1767. Arguments:
  1768. ControlChannel - An open handle to the Cluster Network control device.
  1769. EndpointString - string containing port number assigned to clusnet
  1770. Return Value:
  1771. ERROR_SUCCESS if the operation was successful.
  1772. A Windows error code otherwise.
  1773. --*/
  1774. {
  1775. USHORT port;
  1776. DWORD err;
  1777. DWORD responseSize = 0;
  1778. NTSTATUS status;
  1779. err = ClRtlTcpipStringToEndpoint(EndpointString, &port);
  1780. if (err == ERROR_SUCCESS) {
  1781. // TCP/IP needs the port in host byte-order format.
  1782. // ClRtlTcpipStringToEndpoint returns it in network
  1783. // byte-order format.
  1784. port = ntohs(port);
  1785. status = DoIoctl(
  1786. ControlChannel,
  1787. IOCTL_CX_RESERVE_ENDPOINT,
  1788. &port,
  1789. sizeof(port),
  1790. NULL,
  1791. &responseSize,
  1792. NULL
  1793. );
  1794. err = NtStatusToClusnetError(status);
  1795. }
  1796. return err;
  1797. }
  1798. DWORD
  1799. ClusnetConfigureMulticast(
  1800. IN HANDLE ControlChannel,
  1801. IN CL_NETWORK_ID NetworkId,
  1802. IN ULONG MulticastNetworkBrand,
  1803. IN PVOID MulticastAddress,
  1804. IN ULONG MulticastAddressLength,
  1805. IN PVOID Key,
  1806. IN ULONG KeyLength
  1807. )
  1808. /*++
  1809. Routine Description:
  1810. Configures multicast parameters for the specified network.
  1811. --*/
  1812. {
  1813. NTSTATUS status;
  1814. PCX_CONFIGURE_MULTICAST_REQUEST request;
  1815. DWORD requestSize;
  1816. DWORD requestDataOffset = 0;
  1817. DWORD responseSize = 0;
  1818. //
  1819. // The request size is based on the size and required alignment
  1820. // of each field of data following the structure. If there is no
  1821. // data following the structure, only the structure is required.
  1822. //
  1823. requestSize = sizeof(CX_CONFIGURE_MULTICAST_REQUEST);
  1824. requestDataOffset = requestSize;
  1825. if (MulticastAddressLength != 0) {
  1826. requestSize = ROUND_UP_COUNT(requestSize,
  1827. TYPE_ALIGNMENT(TRANSPORT_ADDRESS)
  1828. ) +
  1829. MulticastAddressLength;
  1830. }
  1831. if (KeyLength != 0) {
  1832. requestSize = ROUND_UP_COUNT(requestSize,
  1833. TYPE_ALIGNMENT(PVOID)
  1834. ) +
  1835. KeyLength;
  1836. }
  1837. //
  1838. // Allocate the request buffer.
  1839. //
  1840. request = LocalAlloc(LMEM_FIXED, requestSize);
  1841. if (request == NULL) {
  1842. return(ERROR_NOT_ENOUGH_MEMORY);
  1843. }
  1844. request->NetworkId = NetworkId;
  1845. request->MulticastNetworkBrand = MulticastNetworkBrand;
  1846. if (MulticastAddress != NULL) {
  1847. request->MulticastAddress = ROUND_UP_COUNT(
  1848. requestDataOffset,
  1849. TYPE_ALIGNMENT(TRANSPORT_ADDRESS)
  1850. );
  1851. MoveMemory(
  1852. (((PUCHAR) request) + request->MulticastAddress),
  1853. MulticastAddress,
  1854. MulticastAddressLength
  1855. );
  1856. request->MulticastAddressLength = MulticastAddressLength;
  1857. requestDataOffset = request->MulticastAddress +
  1858. request->MulticastAddressLength;
  1859. } else {
  1860. request->MulticastAddress = 0;
  1861. request->MulticastAddressLength = 0;
  1862. }
  1863. if (Key != NULL) {
  1864. request->Key = ROUND_UP_COUNT(
  1865. requestDataOffset,
  1866. TYPE_ALIGNMENT(PVOID)
  1867. );
  1868. MoveMemory(
  1869. (((PUCHAR) request) + request->Key),
  1870. Key,
  1871. KeyLength
  1872. );
  1873. request->KeyLength = KeyLength;
  1874. requestDataOffset = request->Key + request->KeyLength;
  1875. } else {
  1876. request->Key = 0;
  1877. request->KeyLength = 0;
  1878. }
  1879. status = DoIoctl(
  1880. ControlChannel,
  1881. IOCTL_CX_CONFIGURE_MULTICAST,
  1882. request,
  1883. requestSize,
  1884. NULL,
  1885. &responseSize,
  1886. NULL
  1887. );
  1888. LocalFree(request);
  1889. return(NtStatusToClusnetError(status));
  1890. } // ClusnetConfigureMulticast
  1891. DWORD
  1892. ClusnetGetMulticastReachableSet(
  1893. IN HANDLE ControlChannel,
  1894. IN CL_NETWORK_ID NetworkId,
  1895. OUT ULONG * NodeScreen
  1896. )
  1897. /*++
  1898. Routine Description:
  1899. Queries the current set of nodes considered reachable by
  1900. a multicast on the specified network.
  1901. Arguments:
  1902. ControlChannel - open clusnet control channel
  1903. NetworkId - multicast network
  1904. NodeScreen - mask of nodes
  1905. Return value:
  1906. ERROR_SUCCESS if the operation was successful.
  1907. A Windows error code otherwise.
  1908. --*/
  1909. {
  1910. NTSTATUS status;
  1911. CX_GET_MULTICAST_REACHABLE_SET_REQUEST request;
  1912. CX_GET_MULTICAST_REACHABLE_SET_RESPONSE response;
  1913. DWORD responseSize = sizeof(response);
  1914. request.Id = NetworkId;
  1915. status = DoIoctl(
  1916. ControlChannel,
  1917. IOCTL_CX_GET_MULTICAST_REACHABLE_SET,
  1918. &request,
  1919. sizeof(request),
  1920. &response,
  1921. &responseSize,
  1922. NULL
  1923. );
  1924. if (status == STATUS_SUCCESS) {
  1925. *NodeScreen = response.NodeScreen;
  1926. }
  1927. return(NtStatusToClusnetError(status));
  1928. } // ClusnetGetMulticastReachableSet
  1929. DWORD
  1930. ClusnetSetIamaliveParam(
  1931. IN HANDLE ControlChannel,
  1932. IN ULONG Timeout,
  1933. IN ClussvcHangAction Action
  1934. )
  1935. /*++
  1936. Routine Description:
  1937. Sets the Timeout and Action to be taken by clusnet in case of clusnet hang.
  1938. Arguments:
  1939. ControlChannel - An open handle to the Cluster Network control device.
  1940. Timeout - Timeout in Secs.
  1941. Action - Action to be taken by Clusnet in case of clussvc hang.
  1942. Return Value:
  1943. ERROR_SUCCESS if the operation was successful.
  1944. A Windows error code otherwise.
  1945. --*/
  1946. {
  1947. NTSTATUS status;
  1948. DWORD responseSize = 0;
  1949. CLUSNET_SET_IAMALIVE_PARAM_REQUEST request;
  1950. request.Timeout = Timeout;
  1951. request.Action = Action;
  1952. status = DoIoctl(
  1953. ControlChannel,
  1954. IOCTL_CLUSNET_SET_IAMALIVE_PARAM,
  1955. &request,
  1956. sizeof(CLUSNET_SET_IAMALIVE_PARAM_REQUEST),
  1957. NULL,
  1958. &responseSize,
  1959. NULL
  1960. );
  1961. return(NtStatusToClusnetError(status));
  1962. } // ClusnetSetIamaliveParam
  1963. DWORD
  1964. ClusnetIamalive(
  1965. IN HANDLE ControlChannel
  1966. )
  1967. /*++
  1968. Routine Description:
  1969. Clussvc to Clusnet Heartbeat Ioctl
  1970. Arguments:
  1971. ControlChannel - An open handle to the Cluster Network control device.
  1972. Return Value:
  1973. ERROR_SUCCESS if the operation was successful.
  1974. A Windows error code otherwise.
  1975. --*/
  1976. {
  1977. NTSTATUS status;
  1978. DWORD requestSize = 0;
  1979. DWORD responseSize = 0;
  1980. status = DoIoctl(
  1981. ControlChannel,
  1982. IOCTL_CLUSNET_IAMALIVE,
  1983. NULL,
  1984. requestSize,
  1985. NULL,
  1986. &responseSize,
  1987. NULL
  1988. );
  1989. return(NtStatusToClusnetError(status));
  1990. } // ClusnetIamalive
  1991. #if DBG
  1992. DWORD
  1993. ClusnetSetDebugMask(
  1994. IN HANDLE ControlChannel,
  1995. IN ULONG Mask
  1996. )
  1997. /*++
  1998. Routine Description:
  1999. Arguments:
  2000. ControlChannel - An open handle to the Cluster Network control device.
  2001. Return Value:
  2002. ERROR_SUCCESS if the operation was successful.
  2003. A Windows error code otherwise.
  2004. --*/
  2005. {
  2006. NTSTATUS status;
  2007. CLUSNET_SET_DEBUG_MASK_REQUEST request;
  2008. DWORD responseSize = 0;
  2009. request.DebugMask = Mask;
  2010. status = DoIoctl(
  2011. ControlChannel,
  2012. IOCTL_CLUSNET_SET_DEBUG_MASK,
  2013. &request,
  2014. sizeof(CLUSNET_SET_DEBUG_MASK_REQUEST),
  2015. NULL,
  2016. &responseSize,
  2017. NULL
  2018. );
  2019. return(NtStatusToClusnetError(status));
  2020. }
  2021. DWORD
  2022. ClusnetOnlinePendingInterface(
  2023. IN HANDLE ControlChannel,
  2024. IN CL_NODE_ID NodeId,
  2025. IN CL_NETWORK_ID NetworkId
  2026. )
  2027. /*++
  2028. Routine Description:
  2029. Arguments:
  2030. ControlChannel - An open handle to the Cluster Network control device.
  2031. Return Value:
  2032. ERROR_SUCCESS if the operation was successful.
  2033. A Windows error code otherwise.
  2034. --*/
  2035. {
  2036. NTSTATUS status;
  2037. CX_ONLINE_PENDING_INTERFACE_REQUEST request;
  2038. DWORD requestSize = sizeof(request);
  2039. DWORD responseSize = 0;
  2040. request.NodeId = NodeId;
  2041. request.NetworkId = NetworkId;
  2042. status = DoIoctl(
  2043. ControlChannel,
  2044. IOCTL_CX_ONLINE_PENDING_INTERFACE,
  2045. &request,
  2046. requestSize,
  2047. NULL,
  2048. &responseSize,
  2049. NULL
  2050. );
  2051. return(NtStatusToClusnetError(status));
  2052. }
  2053. DWORD
  2054. ClusnetOnlineInterface(
  2055. IN HANDLE ControlChannel,
  2056. IN CL_NODE_ID NodeId,
  2057. IN CL_NETWORK_ID NetworkId
  2058. )
  2059. /*++
  2060. Routine Description:
  2061. Arguments:
  2062. ControlChannel - An open handle to the Cluster Network control device.
  2063. Return Value:
  2064. ERROR_SUCCESS if the operation was successful.
  2065. A Windows error code otherwise.
  2066. --*/
  2067. {
  2068. NTSTATUS status;
  2069. CX_ONLINE_INTERFACE_REQUEST request;
  2070. DWORD requestSize = sizeof(request);
  2071. DWORD responseSize = 0;
  2072. request.NodeId = NodeId;
  2073. request.NetworkId = NetworkId;
  2074. status = DoIoctl(
  2075. ControlChannel,
  2076. IOCTL_CX_ONLINE_INTERFACE,
  2077. &request,
  2078. requestSize,
  2079. NULL,
  2080. &responseSize,
  2081. NULL
  2082. );
  2083. return(NtStatusToClusnetError(status));
  2084. }
  2085. DWORD
  2086. ClusnetOfflineInterface(
  2087. IN HANDLE ControlChannel,
  2088. IN CL_NODE_ID NodeId,
  2089. IN CL_NETWORK_ID NetworkId
  2090. )
  2091. /*++
  2092. Routine Description:
  2093. Arguments:
  2094. ControlChannel - An open handle to the Cluster Network control device.
  2095. Return Value:
  2096. ERROR_SUCCESS if the operation was successful.
  2097. A Windows error code otherwise.
  2098. --*/
  2099. {
  2100. NTSTATUS status;
  2101. CX_OFFLINE_INTERFACE_REQUEST request;
  2102. DWORD requestSize = sizeof(request);
  2103. DWORD responseSize = 0;
  2104. request.NodeId = NodeId;
  2105. request.NetworkId = NetworkId;
  2106. status = DoIoctl(
  2107. ControlChannel,
  2108. IOCTL_CX_OFFLINE_INTERFACE,
  2109. &request,
  2110. requestSize,
  2111. NULL,
  2112. &responseSize,
  2113. NULL
  2114. );
  2115. return(NtStatusToClusnetError(status));
  2116. }
  2117. DWORD
  2118. ClusnetFailInterface(
  2119. IN HANDLE ControlChannel,
  2120. IN CL_NODE_ID NodeId,
  2121. IN CL_NETWORK_ID NetworkId
  2122. )
  2123. /*++
  2124. Routine Description:
  2125. Arguments:
  2126. ControlChannel - An open handle to the Cluster Network control device.
  2127. Return Value:
  2128. ERROR_SUCCESS if the operation was successful.
  2129. A Windows error code otherwise.
  2130. --*/
  2131. {
  2132. NTSTATUS status;
  2133. CX_FAIL_INTERFACE_REQUEST request;
  2134. DWORD requestSize = sizeof(request);
  2135. DWORD responseSize = 0;
  2136. request.NodeId = NodeId;
  2137. request.NetworkId = NetworkId;
  2138. status = DoIoctl(
  2139. ControlChannel,
  2140. IOCTL_CX_FAIL_INTERFACE,
  2141. &request,
  2142. requestSize,
  2143. NULL,
  2144. &responseSize,
  2145. NULL
  2146. );
  2147. return(NtStatusToClusnetError(status));
  2148. }
  2149. DWORD
  2150. ClusnetSendMmMsg(
  2151. IN HANDLE ControlChannel,
  2152. IN CL_NODE_ID NodeId,
  2153. IN ULONG Pattern
  2154. )
  2155. /*++
  2156. Routine Description:
  2157. Arguments:
  2158. ControlChannel - An open handle to the Cluster Network control device.
  2159. Return Value:
  2160. ERROR_SUCCESS if the operation was successful.
  2161. A Windows error code otherwise.
  2162. --*/
  2163. {
  2164. NTSTATUS status;
  2165. CX_SEND_MM_MSG_REQUEST request;
  2166. DWORD requestSize = sizeof(request);
  2167. DWORD responseSize = 0;
  2168. DWORD i;
  2169. request.DestNodeId = NodeId;
  2170. for (i=0; i < CX_MM_MSG_DATA_LEN; i++) {
  2171. request.MessageData[i] = Pattern;
  2172. }
  2173. status = DoIoctl(
  2174. ControlChannel,
  2175. IOCTL_CX_SEND_MM_MSG,
  2176. &request,
  2177. requestSize,
  2178. NULL,
  2179. &responseSize,
  2180. NULL
  2181. );
  2182. return(NtStatusToClusnetError(status));
  2183. }
  2184. #endif // DBG