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.

4310 lines
135 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: control.cpp
  4. //
  5. // Module:
  6. //
  7. // Description: Implement class CWlbsControl
  8. //
  9. // Copyright (C) Microsoft Corporation. All rights reserved.
  10. //
  11. // Author: Created 3/2/00
  12. //
  13. //+----------------------------------------------------------------------------
  14. #include "precomp.h"
  15. #include <debug.h>
  16. #include "notification.h"
  17. #include "cluster.h"
  18. #include "control.h"
  19. #include "param.h"
  20. #include "control.tmh" // for event tracing
  21. //
  22. // Used only by WlbsRemoteControl and helper functions FindHostInList and AddHostToList.
  23. //
  24. typedef struct
  25. {
  26. DWORD hostID;
  27. DWORD address;
  28. WCHAR hostName[CVY_MAX_HOST_NAME + 1];
  29. } HOST, * PHOST;
  30. //
  31. // Global variable for the dll instance
  32. //
  33. HINSTANCE g_hInstCtrl;
  34. //
  35. // Helper functions
  36. //
  37. DWORD MapStateFromDriverToApi(DWORD dwDriverState);
  38. //+----------------------------------------------------------------------------
  39. //
  40. // Function: IsLocalHost
  41. //
  42. // Description:
  43. //
  44. // Arguments: CWlbsCluster* pCluster -
  45. // DWORD dwHostID -
  46. //
  47. // Returns: inline bool -
  48. //
  49. // History: fengsun Created Header 3/2/00
  50. //
  51. //+----------------------------------------------------------------------------
  52. inline bool IsLocalHost(CWlbsCluster* pCluster, DWORD dwHostID)
  53. {
  54. if (pCluster == NULL)
  55. {
  56. return false;
  57. }
  58. return dwHostID == WLBS_LOCAL_HOST; // || pCluster->GetHostID() == dwHostID;
  59. }
  60. //+----------------------------------------------------------------------------
  61. //
  62. // Function: FindHostInList
  63. //
  64. // Description: Takes an array of HOST structs and searches it for a match to the parameters
  65. // that identify a unique host: hostID, host IP and host name.
  66. //
  67. // Arguments: DWORD hostID - host ID to search for in the respondedHosts array
  68. // DWORD address - host IP to search for in the respondedHosts array
  69. // PWCHAR hostname - host name to search for in the respondedHosts array
  70. // const PHOST respondedHosts - array of hosts that have responded thus far
  71. // DWORD numhosts - number of entries in respondedHosts
  72. //
  73. // Returns: inline bool - true if match found, false otherwise
  74. //
  75. // History: chrisdar 08.06.01
  76. //
  77. //+----------------------------------------------------------------------------
  78. inline bool FindHostInList(DWORD hostID, DWORD address, PWCHAR hostname, const PHOST respondedHosts, DWORD numhosts)
  79. {
  80. //
  81. // A match is one where and entry in respondedHosts has the same hostid,
  82. // address and hostname. In the case of hostname, NULL (or no name) is an
  83. // allowed value.
  84. //
  85. bool bFound = false;
  86. if (NULL == respondedHosts || 0 == numhosts)
  87. {
  88. return bFound;
  89. }
  90. DWORD dwNumHosts = min(numhosts, WLBS_MAX_HOSTS); // respondedHosts is an arrary of length WLBS_MAX_HOSTS
  91. DWORD dwIndex;
  92. for (dwIndex = 0; dwIndex < dwNumHosts; dwIndex++)
  93. {
  94. if (respondedHosts[dwIndex].hostID == hostID &&
  95. respondedHosts[dwIndex].address == address)
  96. {
  97. //
  98. // Host ID and IP match. Now check the name, allowing for NULL
  99. // as a valid value too.
  100. //
  101. if (NULL != hostname)
  102. {
  103. if (wcscmp(respondedHosts[dwIndex].hostName, hostname) == 0)
  104. {
  105. //
  106. // hostname was provided and we found it in the list.
  107. // NOTE: This branch catches the case where both are empty strings (L"")
  108. //
  109. bFound = true;
  110. break;
  111. }
  112. }
  113. else if (NULL == hostname && 0 == wcscmp(respondedHosts[dwIndex].hostName, L""))
  114. {
  115. //
  116. // hostname is NULL and we have an matching entry in the list with an empty string hostName
  117. //
  118. bFound = true;
  119. break;
  120. }
  121. }
  122. }
  123. return bFound;
  124. }
  125. //+----------------------------------------------------------------------------
  126. //
  127. // Function: AddHostToList
  128. //
  129. // Description: Add an entry to the host list with the specified host parameters.
  130. // This function does NOT validate or ensure the uniqueness of entries.
  131. //
  132. // Arguments: DWORD hostID - host ID to search for in the respondedHosts array
  133. // DWORD address - host IP to search for in the respondedHosts array
  134. // PWCHAR hostname - host name to search for in the respondedHosts array
  135. // const PHOST respondedHosts - array of hosts that have responded thus far
  136. // DWORD numhosts - number of entries in respondedHosts
  137. //
  138. // Returns: inline void
  139. //
  140. // History: chrisdar 08.06.01
  141. //
  142. //+----------------------------------------------------------------------------
  143. inline void AddHostToList(DWORD hostID, DWORD address, PWCHAR hostname, const PHOST respondedHosts, DWORD numhosts)
  144. {
  145. //
  146. // Caller will increment numhosts when we return, whether we succeed or not.
  147. // So don't worry about tracking the number of elements in respondedHosts.
  148. // If the caller doesn't do this, then we will just overwrite the previous
  149. // entry we made.
  150. //
  151. if (numhosts >= WLBS_MAX_HOSTS)
  152. {
  153. return;
  154. }
  155. respondedHosts[numhosts].hostID = hostID;
  156. respondedHosts[numhosts].address = address;
  157. respondedHosts[numhosts].hostName[0] = L'\0'; // Should be zeroed out already, but just in case...
  158. if (NULL != hostname)
  159. {
  160. wcsncpy(respondedHosts[numhosts].hostName, hostname, CVY_MAX_HOST_NAME);
  161. // Terminate the end of the destination string with a NULL, even in the case that we don't need to.
  162. // It's simpler than checking if needed. Worst case we overwrite a NULL with a NULL.
  163. respondedHosts[numhosts].hostName[CVY_MAX_HOST_NAME] = L'\0';
  164. }
  165. }
  166. //+----------------------------------------------------------------------------
  167. //
  168. // Function: QueryPortFromSocket
  169. //
  170. // Synopsis:
  171. // This routine retrieves the port number to which a socket is bound.
  172. //
  173. // Arguments:
  174. // Socket - the socket to be queried
  175. //
  176. // Return Value:
  177. // USHORT - the port number retrieved
  178. //
  179. // History: Created Header 2/10/99
  180. //
  181. //+----------------------------------------------------------------------------
  182. static USHORT QueryPortFromSocket(SOCKET Socket)
  183. {
  184. SOCKADDR_IN Address;
  185. int AddressLength;
  186. AddressLength = sizeof(Address);
  187. getsockname(Socket, (PSOCKADDR)&Address, &AddressLength);
  188. return Address.sin_port;
  189. }
  190. //+----------------------------------------------------------------------------
  191. //
  192. // Function: CWlbsControl::CWlbsControl
  193. //
  194. // Description:
  195. //
  196. // Arguments: None
  197. //
  198. // Returns: Nothing
  199. //
  200. // History: fengsun Created Header 3/2/00
  201. //
  202. //+----------------------------------------------------------------------------
  203. CWlbsControl::CWlbsControl()
  204. {
  205. m_local_ctrl = FALSE;
  206. m_remote_ctrl = FALSE;
  207. m_hdl = INVALID_HANDLE_VALUE;
  208. m_registry_lock = INVALID_HANDLE_VALUE;
  209. m_def_dst_addr = 0;
  210. m_def_timeout = IOCTL_REMOTE_RECV_DELAY;
  211. m_def_port = CVY_DEF_RCT_PORT;
  212. m_def_passw = CVY_DEF_RCT_PASSWORD;
  213. m_dwNumCluster = 0;
  214. for (int i = 0; i < WLBS_MAX_CLUSTERS; i ++)
  215. {
  216. m_cluster_params [i] . cluster = 0;
  217. m_cluster_params [i] . passw = CVY_DEF_RCT_PASSWORD;
  218. m_cluster_params [i] . timeout = IOCTL_REMOTE_RECV_DELAY;
  219. m_cluster_params [i] . port = CVY_DEF_RCT_PORT;
  220. m_cluster_params [i] . dest = 0;
  221. }
  222. ZeroMemory(m_pClusterArray, sizeof(m_pClusterArray));
  223. }
  224. //+----------------------------------------------------------------------------
  225. //
  226. // Function: CWlbsControl::~CWlbsControl
  227. //
  228. // Description:
  229. //
  230. // Arguments: None
  231. //
  232. // Returns: Nothing
  233. //
  234. // History: fengsun Created Header 3/2/00
  235. //
  236. //+----------------------------------------------------------------------------
  237. CWlbsControl::~CWlbsControl()
  238. {
  239. for (DWORD i=0; i< m_dwNumCluster; i++)
  240. {
  241. delete m_pClusterArray[i];
  242. }
  243. if (m_hdl)
  244. {
  245. CloseHandle(m_hdl);
  246. }
  247. if (m_remote_ctrl)
  248. {
  249. WSACleanup(); // WSAStartup is called in Initialize()
  250. }
  251. }
  252. //+----------------------------------------------------------------------------
  253. //
  254. // Function: CWlbsControl::Initialize
  255. //
  256. // Description: Initialization
  257. //
  258. // Arguments: None
  259. //
  260. // Returns: bool - true if succeeded
  261. //
  262. // History: fengsun Created Header 1/25/00
  263. //
  264. //+----------------------------------------------------------------------------
  265. DWORD CWlbsControl::Initialize()
  266. {
  267. TRACE_VERB("->%!FUNC!");
  268. WORD ver;
  269. int ret;
  270. DWORD dwInitResult = 0;
  271. if (IsInitialized())
  272. {
  273. TRACE_INFO("%!FUNC! already initialized. Reinitializing...");
  274. if (!ReInitialize())
  275. {
  276. TRACE_CRIT("%!FUNC! reinitialization failed");
  277. // This check was added for tracing. No abort was done previously on error, so don't do so now.
  278. }
  279. dwInitResult = GetInitResult();
  280. if (WLBS_INIT_ERROR == dwInitResult)
  281. {
  282. TRACE_CRIT("%!FUNC! failed while determining whether nlb is configured for remote or local only activity");
  283. }
  284. TRACE_VERB("<-%!FUNC! returns %d", dwInitResult);
  285. return dwInitResult;
  286. }
  287. if (_tsetlocale (LC_ALL, _TEXT(".OCP")) == NULL)
  288. {
  289. TRACE_CRIT("%!FUNC! illegal locale specified");
  290. // This check was added for tracing. No abort was done previously on error, so don't do so now.
  291. }
  292. /* open Winsock */
  293. WSADATA data;
  294. int iWsaStatus = 0;
  295. DWORD dwStatus = 0;
  296. TRACE_INFO("%!FUNC! initializing winsock");
  297. iWsaStatus = WSAStartup (WINSOCK_VERSION, & data);
  298. if (iWsaStatus == 0)
  299. {
  300. m_remote_ctrl = TRUE;
  301. }
  302. else
  303. {
  304. TRACE_CRIT("%!FUNC! WSAStartup failed with %d", iWsaStatus);
  305. }
  306. /* if succeeded querying local parameters - connect to device */
  307. if (m_hdl != INVALID_HANDLE_VALUE)
  308. {
  309. TRACE_INFO("%!FUNC! closing handle to the device object");
  310. if (!CloseHandle (m_hdl))
  311. {
  312. dwStatus = GetLastError();
  313. TRACE_CRIT("%!FUNC! closing handle to the device object failed with %d", dwStatus);
  314. }
  315. }
  316. TRACE_INFO("%!FUNC! opening (creating handle to) the device object");
  317. m_hdl = CreateFile (_TEXT("\\\\.\\WLBS"), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
  318. if (INVALID_HANDLE_VALUE == m_hdl)
  319. {
  320. dwStatus = GetLastError();
  321. if (dwStatus == ERROR_FILE_NOT_FOUND)
  322. {
  323. //
  324. // Occurs often under bind/unbind stress. Means NLB not installed or not bound.
  325. //
  326. TRACE_INFO("%!FUNC! creating handle to the device object failed with %d", dwStatus);
  327. }
  328. else
  329. {
  330. TRACE_CRIT("%!FUNC! creating handle to the device object failed with %d", dwStatus);
  331. }
  332. dwInitResult = GetInitResult();
  333. if (dwInitResult == WLBS_INIT_ERROR)
  334. {
  335. TRACE_CRIT("%!FUNC! failed while determining whether nlb is configured for remote or local only activity");
  336. }
  337. TRACE_VERB("<-%!FUNC! returns %d", dwInitResult);
  338. return dwInitResult;
  339. }
  340. else
  341. {
  342. TRACE_INFO("%!FUNC! device object opened successfully");
  343. m_local_ctrl = TRUE;
  344. }
  345. //
  346. // enumerate clusters
  347. //
  348. HKEY hKeyWlbs;
  349. DWORD dwError;
  350. const PWCHAR pwszTmpRegPath = L"SYSTEM\\CurrentControlSet\\Services\\WLBS\\Parameters\\Interface";
  351. dwError = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  352. pwszTmpRegPath,
  353. 0L, KEY_READ, & hKeyWlbs);
  354. if (dwError != ERROR_SUCCESS)
  355. {
  356. TRACE_CRIT(L"%!FUNC! failed to open registry %ls with %d", pwszTmpRegPath, dwError);
  357. dwInitResult = GetInitResult();
  358. if (dwInitResult == WLBS_INIT_ERROR)
  359. {
  360. TRACE_CRIT("%!FUNC! failed while determining whether nlb is configured for remote or local only activity");
  361. }
  362. TRACE_VERB("<-%!FUNC! returns %d", dwInitResult);
  363. return dwInitResult;
  364. }
  365. m_dwNumCluster = 0;
  366. TRACE_INFO(L"%!FUNC! enumerating registry subkeys in %ls", pwszTmpRegPath);
  367. for (int index=0;;index++)
  368. {
  369. WCHAR szAdapterGuid[128];
  370. DWORD dwSize = sizeof(szAdapterGuid)/sizeof(szAdapterGuid[0]);
  371. dwError = RegEnumKeyEx(hKeyWlbs, index,
  372. szAdapterGuid, &dwSize,
  373. NULL, NULL, NULL, NULL);
  374. if (dwError != ERROR_SUCCESS)
  375. {
  376. if (dwError != ERROR_NO_MORE_ITEMS)
  377. {
  378. TRACE_CRIT(L"%!FUNC! attempt to enumerate nlb subkey index %i failed with %d", index, dwError);
  379. }
  380. TRACE_INFO(L"%!FUNC! finished enumerating registry subkeys in %ls", pwszTmpRegPath);
  381. break;
  382. }
  383. GUID AdapterGuid;
  384. HRESULT hr = CLSIDFromString(szAdapterGuid, &AdapterGuid);
  385. if (FAILED(hr))
  386. {
  387. TRACE_CRIT(L"%!FUNC! translating to class identifier for string %ls failed with %d", szAdapterGuid, hr);
  388. TRACE_INFO(L"%!FUNC! enumerate next subkey");
  389. continue;
  390. }
  391. IOCTL_CVY_BUF in_buf;
  392. IOCTL_CVY_BUF out_buf;
  393. DWORD status = WlbsLocalControl (m_hdl, AdapterGuid,
  394. IOCTL_CVY_QUERY, & in_buf, & out_buf, NULL);
  395. if (status == WLBS_IO_ERROR)
  396. {
  397. TRACE_CRIT(L"%!FUNC! error querying local host with IOCTL_CVY_QUERY");
  398. TRACE_INFO(L"%!FUNC! enumerate next subkey");
  399. continue;
  400. }
  401. //
  402. // Use index instead of m_dwNumCluster as the cluster index
  403. // m_dwNumCluster will change is a adapter get unbound.
  404. // index will change only if an adapter get removed
  405. //
  406. m_pClusterArray[m_dwNumCluster] = new CWlbsCluster(index);
  407. if (m_pClusterArray[m_dwNumCluster] == NULL)
  408. {
  409. TRACE_CRIT(L"%!FUNC! memory allocation failure while creating nlb cluster configuration instance");
  410. ASSERT(m_pClusterArray[m_dwNumCluster]);
  411. }
  412. else
  413. {
  414. TRACE_VERB(L"%!FUNC! nlb cluster configuration instance created");
  415. if (!m_pClusterArray[m_dwNumCluster]->Initialize(AdapterGuid))
  416. {
  417. TRACE_CRIT(L"%!FUNC! initialization of nlb cluster configuration instance failed. Ignoring...");
  418. }
  419. m_dwNumCluster++;
  420. }
  421. }
  422. dwError = RegCloseKey(hKeyWlbs);
  423. if (dwError != ERROR_SUCCESS)
  424. {
  425. TRACE_CRIT(L"%!FUNC! close registry path %ls failed with %d", pwszTmpRegPath, dwError);
  426. }
  427. dwInitResult = GetInitResult();
  428. if (dwInitResult == WLBS_INIT_ERROR)
  429. {
  430. TRACE_CRIT("%!FUNC! failed while determining whether nlb is configured for remote or local only activity");
  431. }
  432. TRACE_VERB("<-%!FUNC! returns %d", dwInitResult);
  433. return dwInitResult;
  434. }
  435. //+----------------------------------------------------------------------------
  436. //
  437. // Function: CWlbsControl::ReInitialize
  438. //
  439. // Description: Re-Initialization to get the current cluster list
  440. //
  441. // Arguments: None
  442. //
  443. // Returns: bool - true if succeeded
  444. //
  445. // History: fengsun Created Header 1/25/00
  446. //
  447. //+----------------------------------------------------------------------------
  448. bool CWlbsControl::ReInitialize()
  449. {
  450. TRACE_VERB("->%!FUNC!");
  451. ASSERT(m_hdl != INVALID_HANDLE_VALUE);
  452. if ( m_hdl == INVALID_HANDLE_VALUE )
  453. {
  454. TRACE_CRIT("%!FUNC! handle to device object is invalid");
  455. TRACE_VERB("<-%!FUNC! returning false");
  456. return false;
  457. }
  458. HKEY hKeyWlbs;
  459. DWORD dwError;
  460. const PWCHAR pwszTmpRegPath = L"SYSTEM\\CurrentControlSet\\Services\\WLBS\\Parameters\\Interface";
  461. dwError = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  462. pwszTmpRegPath,
  463. 0L, KEY_READ, & hKeyWlbs);
  464. if (dwError != ERROR_SUCCESS)
  465. {
  466. TRACE_CRIT(L"%!FUNC! failed to open registry %ls with %d", pwszTmpRegPath, dwError);
  467. TRACE_VERB("<-%!FUNC! returning false");
  468. return false;
  469. }
  470. //
  471. // Re enumerate the clusters
  472. //
  473. DWORD dwNewNumCluster = 0; // the number of new clusters
  474. bool fClusterExists[WLBS_MAX_CLUSTERS];
  475. CWlbsCluster* NewClusterArray[WLBS_MAX_CLUSTERS];
  476. for (DWORD i=0;i<m_dwNumCluster;i++)
  477. {
  478. fClusterExists[i] = false;
  479. }
  480. TRACE_VERB(L"%!FUNC! enumerating registry subkeys in %ls", pwszTmpRegPath);
  481. for (int index=0;;index++)
  482. {
  483. WCHAR szAdapterGuid[128];
  484. DWORD dwSize = sizeof(szAdapterGuid)/sizeof(szAdapterGuid[0]);
  485. dwError = RegEnumKeyEx(hKeyWlbs, index,
  486. szAdapterGuid, &dwSize,
  487. NULL, NULL, NULL, NULL);
  488. if (dwError != ERROR_SUCCESS)
  489. {
  490. if (dwError != ERROR_NO_MORE_ITEMS)
  491. {
  492. TRACE_CRIT(L"%!FUNC! attempt to enumerate nlb subkey index %i failed with %d", index, dwError);
  493. TRACE_VERB("<-%!FUNC! returning false");
  494. return false;
  495. }
  496. TRACE_INFO(L"%!FUNC! finished enumerating registry subkeys in %ls", pwszTmpRegPath);
  497. break;
  498. }
  499. GUID AdapterGuid;
  500. HRESULT hr = CLSIDFromString(szAdapterGuid, &AdapterGuid);
  501. if (FAILED(hr))
  502. {
  503. TRACE_CRIT(L"%!FUNC! translating to class identifier for string %ls failed with %d", szAdapterGuid, hr);
  504. TRACE_INFO(L"%!FUNC! enumerate next subkey");
  505. continue;
  506. }
  507. IOCTL_CVY_BUF in_buf;
  508. IOCTL_CVY_BUF out_buf;
  509. DWORD status = WlbsLocalControl (m_hdl, AdapterGuid,
  510. IOCTL_CVY_QUERY, & in_buf, & out_buf, NULL);
  511. if (status == WLBS_IO_ERROR)
  512. {
  513. TRACE_CRIT(L"%!FUNC! error querying local host with IOCTL_CVY_QUERY");
  514. TRACE_INFO(L"%!FUNC! enumerate next subkey");
  515. continue;
  516. }
  517. //
  518. // Check if this is a new adapter
  519. //
  520. TRACE_VERB(L"%!FUNC! checking if index %i is a new adapter", index);
  521. for (DWORD j=0; j<m_dwNumCluster; j++)
  522. {
  523. ASSERT(m_pClusterArray[j]);
  524. if (IsEqualGUID(AdapterGuid, m_pClusterArray[j]->GetAdapterGuid()))
  525. {
  526. ASSERT(fClusterExists[j] == false);
  527. fClusterExists[j] = true;
  528. //
  529. // Since adapter could be added or removed, since last time,
  530. // The index could be changed
  531. //
  532. m_pClusterArray[j]->m_dwConfigIndex = index;
  533. break;
  534. }
  535. }
  536. //
  537. // It is a new adapter
  538. //
  539. if (j == m_dwNumCluster)
  540. {
  541. TRACE_VERB(L"%!FUNC! index %i is a new adapter", index);
  542. CWlbsCluster* pCluster = new CWlbsCluster(index);
  543. if (pCluster == NULL)
  544. {
  545. TRACE_CRIT(L"%!FUNC! memory allocation failure for new cluster adapter instance for index %i", index);
  546. ASSERT(pCluster);
  547. }
  548. else
  549. {
  550. TRACE_VERB(L"%!FUNC! cluster instance for adapter index %i successfully created", index);
  551. if (!pCluster->Initialize(AdapterGuid))
  552. {
  553. TRACE_CRIT(L"%!FUNC! initialize of cluster instance for adapter index %i failed.", index);
  554. }
  555. //
  556. // Add
  557. //
  558. TRACE_VERB(L"%!FUNC! cluster instance for adapter index %i added to cluster array", index);
  559. NewClusterArray[dwNewNumCluster] = pCluster;
  560. dwNewNumCluster++;
  561. }
  562. }
  563. }
  564. dwError = RegCloseKey(hKeyWlbs);
  565. if (dwError != ERROR_SUCCESS)
  566. {
  567. TRACE_CRIT(L"%!FUNC! close registry path %ls failed with %d", pwszTmpRegPath, dwError);
  568. }
  569. //
  570. // Create the new cluster array
  571. //
  572. TRACE_VERB(L"%!FUNC! creating the new cluster array");
  573. for (i=0; i< m_dwNumCluster; i++)
  574. {
  575. if (!fClusterExists[i])
  576. {
  577. TRACE_VERB(L"%!FUNC! deleting cluster instance %i the no longer exists", i);
  578. delete m_pClusterArray[i];
  579. }
  580. else
  581. {
  582. //
  583. // Reload settings
  584. //
  585. if (!m_pClusterArray[i]->ReInitialize())
  586. {
  587. TRACE_CRIT(L"%!FUNC! reinitialize of cluster instance %i failed. It will be kept.", i);
  588. }
  589. TRACE_INFO(L"%!FUNC! keeping cluster instance %i", i);
  590. NewClusterArray[dwNewNumCluster] = m_pClusterArray[i];
  591. dwNewNumCluster++;
  592. }
  593. m_pClusterArray[i] = NULL;
  594. }
  595. //
  596. // Copy the array back
  597. //
  598. TRACE_VERB(L"%!FUNC! copying cluster array");
  599. m_dwNumCluster = dwNewNumCluster;
  600. CopyMemory(m_pClusterArray, NewClusterArray, m_dwNumCluster * sizeof(m_pClusterArray[0]));
  601. ASSERT(m_pClusterArray[m_dwNumCluster] == NULL);
  602. TRACE_VERB("<-%!FUNC! returning true");
  603. return true;
  604. }
  605. //+----------------------------------------------------------------------------
  606. //
  607. // Function: MapStateFromDriverToApi
  608. //
  609. // Description: Map the state return from wlbs driver to the API state
  610. //
  611. // Arguments: DWORD dwDriverState -
  612. //
  613. // Returns: DWORD -
  614. //
  615. // History: fengsun Created Header 1/25/00
  616. //
  617. //+----------------------------------------------------------------------------
  618. DWORD MapStateFromDriverToApi(DWORD dwDriverState)
  619. {
  620. struct STATE_MAP
  621. {
  622. DWORD dwDriverState;
  623. DWORD dwApiState;
  624. }
  625. StateMap[] =
  626. {
  627. {IOCTL_CVY_ALREADY, WLBS_ALREADY},
  628. {IOCTL_CVY_BAD_PARAMS, WLBS_BAD_PARAMS},
  629. {IOCTL_CVY_NOT_FOUND, WLBS_NOT_FOUND},
  630. {IOCTL_CVY_STOPPED, WLBS_STOPPED},
  631. {IOCTL_CVY_SUSPENDED, WLBS_SUSPENDED},
  632. {IOCTL_CVY_CONVERGING, WLBS_CONVERGING},
  633. {IOCTL_CVY_SLAVE, WLBS_CONVERGED},
  634. {IOCTL_CVY_MASTER, WLBS_DEFAULT},
  635. {IOCTL_CVY_BAD_PASSWORD, WLBS_BAD_PASSW},
  636. {IOCTL_CVY_DRAINING, WLBS_DRAINING},
  637. {IOCTL_CVY_DRAINING_STOPPED, WLBS_DRAIN_STOP},
  638. {IOCTL_CVY_DISCONNECTED, WLBS_DISCONNECTED},
  639. {IOCTL_CVY_GENERIC_FAILURE, WLBS_FAILURE},
  640. {IOCTL_CVY_REQUEST_REFUSED, WLBS_REFUSED},
  641. {IOCTL_CVY_OK, WLBS_OK}
  642. };
  643. for (int i=0; i<sizeof(StateMap) /sizeof(StateMap[0]); i++)
  644. {
  645. if (StateMap[i].dwDriverState == dwDriverState)
  646. {
  647. return StateMap[i].dwApiState;
  648. }
  649. }
  650. //
  651. // Default
  652. //
  653. return WLBS_OK;
  654. }
  655. //+----------------------------------------------------------------------------
  656. //
  657. // Function: CWlbsControl::GetClusterFromIp
  658. //
  659. // Description: Get the cluster object from IP
  660. //
  661. // Arguments: DWORD dwClusterIp -
  662. //
  663. // Returns: CWlbsCluster* - Caller can NOT free the return object
  664. //
  665. // History: fengsun Created Header 3/9/00
  666. //
  667. //+----------------------------------------------------------------------------
  668. inline
  669. CWlbsCluster* CWlbsControl::GetClusterFromIp(DWORD dwClusterIp)
  670. {
  671. TRACE_VERB("->%!FUNC! look for cluster 0x%lx", dwClusterIp);
  672. for (DWORD i=0; i< m_dwNumCluster; i++)
  673. {
  674. if(m_pClusterArray[i]->GetClusterIp() == dwClusterIp)
  675. {
  676. TRACE_VERB("<-%!FUNC! found cluster instance");
  677. return m_pClusterArray[i];
  678. }
  679. }
  680. TRACE_VERB("<-%!FUNC! cluster instance not found");
  681. return NULL;
  682. }
  683. //+----------------------------------------------------------------------------
  684. //
  685. // Function: CWlbsControl::GetClusterFromAdapter
  686. //
  687. // Description: Get the cluster object from adapter guid
  688. //
  689. // Arguments: GUID *pAdapterGuid -- GUID of the adapter.
  690. //
  691. // Returns: CWlbsCluster* - Caller can NOT free the return object
  692. //
  693. // History: JosephJ Created 4/20/01
  694. //
  695. //+----------------------------------------------------------------------------
  696. inline
  697. CWlbsCluster* CWlbsControl::GetClusterFromAdapter(IN const GUID &AdapterGuid)
  698. {
  699. TRACE_VERB("->%!FUNC!");
  700. for (DWORD i=0; i< m_dwNumCluster; i++)
  701. {
  702. const GUID& Guid = m_pClusterArray[i]->GetAdapterGuid();
  703. if (IsEqualGUID(Guid, AdapterGuid))
  704. {
  705. TRACE_VERB("<-%!FUNC! found cluster instance");
  706. return m_pClusterArray[i];
  707. }
  708. }
  709. TRACE_VERB("<-%!FUNC! cluster instance not found");
  710. return NULL;
  711. }
  712. //+----------------------------------------------------------------------------
  713. //
  714. // Function: CWlbsControl::ValidateParam
  715. //
  716. // Description: Validate the specified WLBS cluster parameter. It has no side effects other to munge paramp, for example reformatting
  717. // IP addresses into canonical form.
  718. //
  719. // Arguments: paramp -- params to validate
  720. //
  721. // Returns: TRUE if params look valid, false otherwise.
  722. //
  723. // History: JosephJ Created 4/25/01
  724. //
  725. //+----------------------------------------------------------------------------
  726. BOOL
  727. CWlbsControl::ValidateParam(
  728. IN OUT PWLBS_REG_PARAMS paramp
  729. )
  730. {
  731. return ::WlbsValidateParams(paramp)!=0;
  732. }
  733. //+----------------------------------------------------------------------------
  734. //
  735. // Function: CWlbsControlWrapper::GetClusterFromIpOrIndex
  736. //
  737. // Description:
  738. //
  739. // Arguments: DWORD dwClusterIpOrIndex -
  740. //
  741. // Returns: CWlbsCluster* -
  742. //
  743. // History: fengsun Created Header 7/3/00
  744. //
  745. //+----------------------------------------------------------------------------
  746. CWlbsCluster* CWlbsControl::GetClusterFromIpOrIndex(DWORD dwClusterIpOrIndex)
  747. {
  748. TRACE_VERB("->%!FUNC! cluster 0x%lx", dwClusterIpOrIndex);
  749. for (DWORD i=0; i<m_dwNumCluster; i++)
  750. {
  751. if (m_pClusterArray[i]->GetClusterIpOrIndex(this) == dwClusterIpOrIndex)
  752. {
  753. TRACE_VERB("<-%!FUNC! instance found");
  754. return m_pClusterArray[i];
  755. }
  756. }
  757. TRACE_VERB("<-%!FUNC! cluster instance not found");
  758. return NULL;
  759. }
  760. /*
  761. * Function: CWlbsControlWrapper::IsClusterMember
  762. * Description: This function searches the list of known NLB clusters on this
  763. * host to determine whether or not this host is a member of a
  764. * given cluster.
  765. * Author: shouse, Created 4.16.01
  766. */
  767. BOOLEAN CWlbsControl::IsClusterMember (DWORD dwClusterIp)
  768. {
  769. TRACE_VERB("->%!FUNC! cluster 0x%lx", dwClusterIp);
  770. for (DWORD i = 0; i < m_dwNumCluster; i++) {
  771. if (m_pClusterArray[i]->GetClusterIp() == dwClusterIp)
  772. {
  773. TRACE_VERB("<-%!FUNC! returning true");
  774. return TRUE;
  775. }
  776. }
  777. TRACE_VERB("<-%!FUNC! returning false");
  778. return FALSE;
  779. }
  780. //+----------------------------------------------------------------------------
  781. //
  782. // Function: CWlbsControl::EnumClusterObjects
  783. //
  784. // Description: Get a list of cluster objects
  785. //
  786. // Arguments: OUT CWlbsCluster** &pdwClusters - The memory is internal to CWlbsControl
  787. /// Caller can NOT free the pdwClusters memory
  788. // OUT DWORD* pdwNum -
  789. //
  790. // Returns: DWORD -
  791. //
  792. // History: fengsun Created Header 3/3/00
  793. //
  794. //+----------------------------------------------------------------------------
  795. DWORD CWlbsControl::EnumClusterObjects(OUT CWlbsCluster** &ppClusters, OUT DWORD* pdwNum)
  796. {
  797. TRACE_VERB("->%!FUNC!");
  798. ASSERT(pdwNum);
  799. ppClusters = m_pClusterArray;
  800. *pdwNum = m_dwNumCluster;
  801. TRACE_VERB("<-%!FUNC!");
  802. return ERROR_SUCCESS;
  803. }
  804. //+----------------------------------------------------------------------------
  805. //
  806. // Function: CWlbsControl::EnumClusters
  807. //
  808. // Description: Get a list of cluster IP or index
  809. //
  810. // Arguments: OUT DWORD* pdwAddresses -
  811. // IN OUT DWORD* pdwNum - IN size of the buffer, OUT element returned
  812. //
  813. // Returns: DWORD - WLBS error code.
  814. //
  815. // History: fengsun Created Header 3/3/00
  816. //
  817. //+----------------------------------------------------------------------------
  818. DWORD CWlbsControl::EnumClusters(OUT DWORD* pdwAddresses, IN OUT DWORD* pdwNum)
  819. {
  820. TRACE_VERB("->%!FUNC!");
  821. if (pdwNum == NULL)
  822. {
  823. TRACE_CRIT("%!FUNC! input array size not provided");
  824. TRACE_VERB("<-%!FUNC! returning %d", WLBS_BAD_PARAMS);
  825. return WLBS_BAD_PARAMS;
  826. }
  827. if (pdwAddresses == NULL || *pdwNum < m_dwNumCluster)
  828. {
  829. *pdwNum = m_dwNumCluster;
  830. TRACE_CRIT("%!FUNC! input buffer is not large enough for cluster list");
  831. TRACE_VERB("<-%!FUNC! returning %d", ERROR_MORE_DATA);
  832. return ERROR_MORE_DATA;
  833. }
  834. *pdwNum = m_dwNumCluster;
  835. for (DWORD i=0; i< m_dwNumCluster; i++)
  836. {
  837. pdwAddresses[i] = m_pClusterArray[i]->GetClusterIpOrIndex(this);
  838. }
  839. TRACE_VERB("<-%!FUNC! returning %d", WLBS_OK);
  840. return WLBS_OK;
  841. }
  842. //+----------------------------------------------------------------------------
  843. //
  844. // Function: WlbsOpen
  845. //
  846. // Description: Opens & returns handle to NLB driver.
  847. // Caller must call CloseHandle() after use of handle
  848. //
  849. // Arguments: None
  850. //
  851. // Returns: Handle to Driver
  852. //
  853. // History: KarthicN, Created 8/28/01
  854. //
  855. //+----------------------------------------------------------------------------
  856. HANDLE WINAPI WlbsOpen()
  857. {
  858. HANDLE hdl;
  859. TRACE_VERB("->%!FUNC!");
  860. hdl = CreateFile (_TEXT("\\\\.\\WLBS"), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
  861. if (INVALID_HANDLE_VALUE == hdl)
  862. {
  863. TRACE_CRIT("%!FUNC! creating handle to the device object failed with %d", GetLastError());
  864. }
  865. TRACE_VERB("<-%!FUNC! returning %p", hdl);
  866. return hdl;
  867. }
  868. //+----------------------------------------------------------------------------
  869. //
  870. // Function: WlbsLocalControlWrapper
  871. //
  872. // Description: Wrapper around WlbsLocalControl()
  873. //
  874. // Arguments: handle to NLB driver, Adapter GUID, Ioctl
  875. //
  876. // Returns: Status Code
  877. //
  878. // History: KarthicN, Created 8/28/01
  879. //
  880. //+----------------------------------------------------------------------------
  881. DWORD WINAPI WlbsLocalClusterControl(
  882. IN HANDLE NlbHdl,
  883. IN const GUID * pAdapterGuid,
  884. IN LONG ioctl,
  885. IN DWORD Vip,
  886. IN DWORD PortNum,
  887. OUT DWORD* pdwHostMap
  888. )
  889. {
  890. TRACE_VERB("->%!FUNC! ioctl : 0x%x, Vip : 0x%x, Port : 0x%x", ioctl, Vip, PortNum);
  891. DWORD status;
  892. IOCTL_CVY_BUF in_buf;
  893. IOCTL_CVY_BUF out_buf;
  894. IOCTL_LOCAL_OPTIONS Options, *pOptions;
  895. pOptions = NULL;
  896. ZeroMemory(&in_buf, sizeof(in_buf));
  897. //
  898. // We only support cluster-wide operations...
  899. //
  900. switch(ioctl)
  901. {
  902. case IOCTL_CVY_CLUSTER_ON:
  903. case IOCTL_CVY_CLUSTER_OFF:
  904. case IOCTL_CVY_CLUSTER_SUSPEND:
  905. case IOCTL_CVY_CLUSTER_RESUME:
  906. case IOCTL_CVY_CLUSTER_DRAIN:
  907. case IOCTL_CVY_QUERY:
  908. break;
  909. case IOCTL_CVY_PORT_ON:
  910. case IOCTL_CVY_PORT_OFF:
  911. case IOCTL_CVY_PORT_DRAIN:
  912. ZeroMemory(&Options, sizeof(Options));
  913. Options.common.port.flags = 0;
  914. Options.common.port.vip = Vip;
  915. pOptions = &Options;
  916. in_buf.data.port.num = PortNum;
  917. break;
  918. case IOCTL_CVY_QUERY_PORT_STATE:
  919. ZeroMemory(&Options, sizeof(Options));
  920. Options.common.state.port.VirtualIPAddress = Vip;
  921. Options.common.state.port.Num = (USHORT) PortNum;
  922. pOptions = &Options;
  923. break;
  924. default:
  925. status = WLBS_BAD_PARAMS;
  926. TRACE_CRIT("%!FUNC! requested ioctl is not allowed. Only cluster-wide operations can be performed.");
  927. goto end;
  928. }
  929. status = WlbsLocalControl (NlbHdl, *pAdapterGuid,
  930. ioctl, & in_buf, & out_buf, pOptions);
  931. if (status != WLBS_IO_ERROR)
  932. {
  933. // For Query, return "Cluster State" as status
  934. if (ioctl == IOCTL_CVY_QUERY)
  935. {
  936. // If asked for, return host map
  937. if (pdwHostMap)
  938. {
  939. *pdwHostMap = out_buf.data.query.host_map;
  940. }
  941. status = MapStateFromDriverToApi (out_buf.data.query.state);
  942. }
  943. // For QueryPortState, return "Port State" as status
  944. else if (ioctl == IOCTL_CVY_QUERY_PORT_STATE)
  945. {
  946. status = (DWORD)(pOptions->common.state.port.Status);
  947. }
  948. // For everything else, return "operation's result" as status
  949. else
  950. {
  951. status = MapStateFromDriverToApi (out_buf.ret_code);
  952. }
  953. TRACE_INFO("%!FUNC! ioctl request was made and returned nlb or port status %d", status);
  954. }
  955. else
  956. {
  957. TRACE_CRIT("%!FUNC! call to control local cluster failed with WLBS_IO_ERROR");
  958. }
  959. end:
  960. TRACE_VERB("<-%!FUNC! returning %d", status);
  961. return status;
  962. }
  963. //+----------------------------------------------------------------------------
  964. //
  965. // Function: GetSrcAddress
  966. //
  967. // Description: Get the source address of the local host
  968. //
  969. // Arguments:
  970. //
  971. // Returns: DWORD - the IP address
  972. //
  973. // History: chrisdar 2002.01.17 Created. Copied from CWlbsControl::Initialize
  974. //
  975. //+----------------------------------------------------------------------------
  976. DWORD GetSrcAddress()
  977. {
  978. DWORD dwSrcAddress = 0;
  979. DWORD dwStatus;
  980. CHAR buf [CVY_STR_SIZE];
  981. struct hostent * host;
  982. TRACE_VERB("->");
  983. if (gethostname (buf, CVY_STR_SIZE) == SOCKET_ERROR)
  984. {
  985. dwStatus = WSAGetLastError();
  986. TRACE_CRIT("gethostname failed with %d", dwStatus);
  987. goto end;
  988. }
  989. // Note: msdn says this api call has been deprecated and should be replaced by getaddrinfo
  990. host = gethostbyname (buf);
  991. if (host == NULL)
  992. {
  993. dwStatus = WSAGetLastError();
  994. TRACE_CRIT("gethostbyname failed with %d", dwStatus);
  995. goto end;
  996. }
  997. if (((struct in_addr *) (host -> h_addr)) -> s_addr == 0)
  998. {
  999. TRACE_CRIT("no IP address in host structure");
  1000. goto end;
  1001. }
  1002. dwSrcAddress = ((struct in_addr *) (host -> h_addr)) -> s_addr;
  1003. end:
  1004. TRACE_VERB("<- returning source address 0x%x", dwSrcAddress);
  1005. return dwSrcAddress;
  1006. }
  1007. //+----------------------------------------------------------------------------
  1008. //
  1009. // Function: GetRemoteControlSocket
  1010. //
  1011. // Description: Create, configure and bind a socket for remote control operations
  1012. //
  1013. // Arguments: SOCKET* pSock - the socket to populate
  1014. // DWORD dwDestIP - the destination IP (the cluster we will talk to)
  1015. // DWORD dwDestPort - the destination port. Needed so that the created
  1016. // socket doesn't use this port in case the local host
  1017. // is a member of the cluster that should handle the
  1018. // remote control request.
  1019. // BOOL isLocal - Is this host a member of the cluster that will
  1020. // receive the remote control request?
  1021. //
  1022. // Returns: DWORD - 0 means success. Otherwise, the return value is a socket error.
  1023. // pSock points to INVALID_SOCKET if this function fails.
  1024. //
  1025. // History: chrisdar 2002.01.17 Created. Moved content of here from
  1026. // CWlbsControl::WlbsRemoteControl
  1027. //
  1028. //+----------------------------------------------------------------------------
  1029. DWORD GetRemoteControlSocket(SOCKET* pSock, DWORD dwDestIP, WORD wDestPort, BOOL isLocal)
  1030. {
  1031. SOCKADDR_IN caddr;
  1032. DWORD dwStatus = 0; // For Winsock calls. MSDN says a value of "0" resets the last
  1033. // error when retrieving a winsock error, so we use it to indicate success.
  1034. DWORD mode = 1; // Indicates to ioctlsocket that the socket mode is non-blocking
  1035. BOOL fReady = FALSE; // "Ready" means we have a bound socket, and it is not bound to dwDestPort.
  1036. const DWORD dwRetryCount = 5;
  1037. TRACE_VERB("-> dwDestIP = 0x%x, wDestPort = 0x%x, host is member of the cluster: %ls", dwDestIP, wDestPort, isLocal ? L"true" : L"false");
  1038. ASSERT (pSock != NULL);
  1039. *pSock = INVALID_SOCKET;
  1040. caddr . sin_family = AF_INET;
  1041. caddr . sin_port = htons (0);
  1042. //
  1043. // We keep trying to bind a socket until:
  1044. // 1) We succeed, or
  1045. // 2) We exhaust all options at our disposal, which are:
  1046. // a) Bind using src IP = cluster IP if we are part of the cluster
  1047. // b) Bind to any IP if a) fails or we aren't part of the cluster
  1048. //
  1049. // The requirement is that the source port we use for the bound socket must not be the
  1050. // remote control port (dwDestPort) if we are a member of that cluster. The impl below
  1051. // assumes that we shouldn't use this as a source port under any circumstance.
  1052. //
  1053. // Change to use Retries max 5
  1054. for (DWORD i=0; i<dwRetryCount; i++)
  1055. {
  1056. //
  1057. // Create the socket
  1058. //
  1059. ASSERT(*pSock == INVALID_SOCKET);
  1060. *pSock = socket (AF_INET, SOCK_DGRAM, 0);
  1061. if (*pSock == INVALID_SOCKET)
  1062. {
  1063. dwStatus = WSAGetLastError();
  1064. TRACE_CRIT("%!FUNC! socket create failed with 0x%x", dwStatus);
  1065. goto end;
  1066. }
  1067. //
  1068. // Set socket to nonblocking mode
  1069. //
  1070. mode = 1;
  1071. if (ioctlsocket (*pSock, FIONBIO, & mode) == SOCKET_ERROR)
  1072. {
  1073. dwStatus = WSAGetLastError();
  1074. TRACE_CRIT("%!FUNC! setting io mode of ioctlsocket failed with 0x%x", dwStatus);
  1075. goto end;
  1076. }
  1077. //
  1078. // If this host is part of the cluster to be controlled, we'll first try binding
  1079. // with the VIP. If this fails or if this host is *not* part of the cluster,
  1080. // we'll try binding with INADDR_ANY.
  1081. //
  1082. caddr . sin_addr . s_addr = htonl (INADDR_ANY);
  1083. if (isLocal)
  1084. {
  1085. caddr . sin_addr . s_addr = dwDestIP;
  1086. }
  1087. BOOL fBound = FALSE;
  1088. if (bind (*pSock, (LPSOCKADDR) & caddr, sizeof (caddr)) != SOCKET_ERROR)
  1089. {
  1090. fBound = TRUE;
  1091. }
  1092. else if (isLocal)
  1093. {
  1094. dwStatus = WSAGetLastError();
  1095. TRACE_CRIT("%!FUNC! socket bind to local cluster IP failed with 0x%x", dwStatus);
  1096. //
  1097. // Try to bind with any IP. Reset return status to "no error" since we will try again.
  1098. //
  1099. caddr . sin_addr . s_addr = htonl (INADDR_ANY);
  1100. dwStatus = 0;
  1101. if (bind (*pSock, (LPSOCKADDR) & caddr, sizeof (caddr)) != SOCKET_ERROR)
  1102. {
  1103. fBound = TRUE;
  1104. }
  1105. else
  1106. {
  1107. dwStatus = WSAGetLastError();
  1108. TRACE_CRIT("%!FUNC! socket bind to INADDR_ANY failed with 0x%x", dwStatus);
  1109. goto end;
  1110. }
  1111. }
  1112. ASSERT(fBound);
  1113. //
  1114. // Check the client-side port we are bound to. If it is the REMOTE control port
  1115. // (dwDestPort) and we are a member of any cluster, then this is a problem. We
  1116. // will just avoid this case completely and always force winsock to bind again.
  1117. //
  1118. if (QueryPortFromSocket(*pSock) == htons (wDestPort))
  1119. {
  1120. TRACE_INFO("%!FUNC! source port will equal dest port. Close socket and open a new one.");
  1121. if (closesocket (*pSock) == SOCKET_ERROR)
  1122. {
  1123. dwStatus = WSAGetLastError();
  1124. TRACE_CRIT("%!FUNC! closesocket failed with 0x%x", dwStatus);
  1125. *pSock = INVALID_SOCKET;
  1126. goto end;
  1127. }
  1128. *pSock = INVALID_SOCKET;
  1129. }
  1130. else
  1131. {
  1132. //
  1133. // This is the only place where we exit the while loop without an error.
  1134. //
  1135. fReady = TRUE;
  1136. break;
  1137. }
  1138. }
  1139. end:
  1140. //
  1141. // Something failed
  1142. //
  1143. if (!fReady)
  1144. {
  1145. if (*pSock != INVALID_SOCKET)
  1146. {
  1147. //
  1148. // Ignore return value of close socket because we don't care if it fails here.
  1149. //
  1150. (VOID) closesocket(*pSock);
  1151. *pSock = INVALID_SOCKET;
  1152. }
  1153. }
  1154. TRACE_VERB("<-%!FUNC! returning %u", dwStatus);
  1155. return dwStatus;
  1156. }
  1157. //+----------------------------------------------------------------------------
  1158. //
  1159. // Function: WlbsRemoteControlInternal
  1160. //
  1161. // Description: Perform cluster wide remote control operation
  1162. //
  1163. // Arguments: LONG ioctl -
  1164. // PIOCTL_CVY_BUF pin_bufp -
  1165. // PIOCTL_CVY_BUF pout_bufp -
  1166. // PWLBS_RESPONSE pcvy_resp -
  1167. // PDWORD nump -
  1168. // DWORD trg_addr -
  1169. // DWORD hst_addr
  1170. // PIOCTL_REMOTE_OPTIONS optionsp -
  1171. // PFN_QUERY_CALLBACK pfnQueryCallBack - function pointer for callback.
  1172. // Used only for remote queries.
  1173. //
  1174. // Returns: DWORD -
  1175. //
  1176. // History: chrisdar 2002.01.17 Created. Moved content of CWlbsControl::WlbsRemoteControl
  1177. // here so that it can be called from outside the wrapper class.
  1178. //
  1179. //+----------------------------------------------------------------------------
  1180. DWORD
  1181. WlbsRemoteControlInternal(
  1182. LONG ioctl,
  1183. PIOCTL_CVY_BUF pin_bufp,
  1184. PIOCTL_CVY_BUF pout_bufp,
  1185. PWLBS_RESPONSE pcvy_resp,
  1186. PDWORD nump,
  1187. DWORD trg_addr,
  1188. DWORD hst_addr,
  1189. PIOCTL_REMOTE_OPTIONS optionsp,
  1190. BOOL isLocal,
  1191. PFN_QUERY_CALLBACK pfnQueryCallBack,
  1192. DWORD timeout,
  1193. WORD port,
  1194. DWORD dst_addr,
  1195. DWORD passw
  1196. )
  1197. {
  1198. INT ret;
  1199. BOOLEAN responded [WLBS_MAX_HOSTS], heard;
  1200. const BOOL broadcast = TRUE; // Used by ioctlsocket for socket options if we are part of the cluster receiving the remote control request.
  1201. DWORD num_sends, num_recvs;
  1202. SOCKET sock = INVALID_SOCKET;
  1203. SOCKADDR_IN saddr;
  1204. DWORD i, hosts;
  1205. IOCTL_REMOTE_HDR rct_req;
  1206. IOCTL_REMOTE_HDR rct_rep;
  1207. PIOCTL_CVY_BUF in_bufp = & rct_req . ctrl;
  1208. DWORD dwStatus = WLBS_INIT_ERROR;
  1209. DWORD dwSrcAddr;
  1210. HOST respondedHosts[WLBS_MAX_HOSTS]; // Array of hosts that have responded to this remote control request. Only used for query?????
  1211. WCHAR* pszTmpHostName = NULL;
  1212. TRACE_VERB("-> ioctl %d, trg_addr 0x%x, hst_addr 0x%x, dst_addr 0x%x, timeout %d, port 0x%x, local host is a member of the cluster: %ls",
  1213. ioctl,
  1214. trg_addr,
  1215. hst_addr,
  1216. dst_addr,
  1217. timeout,
  1218. port,
  1219. isLocal ? L"true" : L"false");
  1220. hosts = 0;
  1221. dwSrcAddr = GetSrcAddress();
  1222. if(dwSrcAddr == 0)
  1223. {
  1224. TRACE_CRIT("GetSrcAddress failed...aborting");
  1225. dwStatus = WLBS_INIT_ERROR;
  1226. goto end;
  1227. }
  1228. //
  1229. // Setup parameters
  1230. //
  1231. ZeroMemory((PVOID)&rct_req, sizeof(IOCTL_REMOTE_HDR));
  1232. ZeroMemory(respondedHosts, sizeof(HOST)*WLBS_MAX_HOSTS);
  1233. * in_bufp = * pin_bufp;
  1234. if (dst_addr == 0)
  1235. {
  1236. dst_addr = trg_addr;
  1237. }
  1238. rct_req . code = IOCTL_REMOTE_CODE;
  1239. rct_req . version = CVY_VERSION_FULL;
  1240. rct_req . id = GetTickCount ();
  1241. rct_req . cluster = trg_addr;
  1242. rct_req . host = hst_addr;
  1243. rct_req . addr = dwSrcAddr;
  1244. rct_req . password = passw;
  1245. rct_req . ioctrl = ioctl;
  1246. if (optionsp)
  1247. rct_req.options = *optionsp;
  1248. //
  1249. // Create a socket and set client-side properties
  1250. //
  1251. dwStatus = GetRemoteControlSocket(&sock, trg_addr, port, isLocal);
  1252. if (dwStatus != 0)
  1253. {
  1254. TRACE_CRIT("bind to socket failed with 0x%x", dwStatus);
  1255. goto end;
  1256. }
  1257. //
  1258. // Set up server side of socket
  1259. //
  1260. saddr . sin_family = AF_INET;
  1261. saddr . sin_port = htons (port);
  1262. //
  1263. // See below. We override this value if we are a member of the cluster receiving the remote control request.
  1264. //
  1265. saddr . sin_addr . s_addr = dst_addr;
  1266. if (isLocal)
  1267. {
  1268. ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) & broadcast,
  1269. sizeof (broadcast));
  1270. if (ret == SOCKET_ERROR)
  1271. {
  1272. dwStatus = WSAGetLastError();
  1273. TRACE_CRIT("setsocketopt failed with 0x%x", dwStatus);
  1274. goto end;
  1275. }
  1276. saddr . sin_addr . s_addr = INADDR_BROADCAST;
  1277. }
  1278. //
  1279. // Setup for remote control request
  1280. //
  1281. for (i = 0; i < WLBS_MAX_HOSTS; i ++)
  1282. responded [i] = FALSE;
  1283. heard = FALSE;
  1284. for (num_sends = 0; num_sends < IOCTL_REMOTE_SEND_RETRIES; num_sends ++)
  1285. {
  1286. /* Set "access bits" in request IOCTL code to use remote (control) settings ie. FILE_ANY_ACCESS */
  1287. SET_IOCTL_ACCESS_BITS_TO_REMOTE(rct_req.ioctrl)
  1288. //
  1289. // Send a remote control request
  1290. //
  1291. ret = sendto (sock, (PCHAR) & rct_req, sizeof (rct_req), 0,
  1292. (LPSOCKADDR) & saddr, sizeof (saddr));
  1293. if (ret == SOCKET_ERROR)
  1294. {
  1295. //
  1296. // Use local scope variable because a failure here isn't a condition for aborting.
  1297. //
  1298. DWORD dwTmpStatus = WSAGetLastError();
  1299. TRACE_CRIT("sendto failed with 0x%x. Sleep %d then retry...", dwTmpStatus, timeout);
  1300. //
  1301. // Sendto could fail if the adapter is too busy. Allow retry.
  1302. //
  1303. Sleep (timeout);
  1304. continue;
  1305. }
  1306. if (ret != sizeof (rct_req))
  1307. {
  1308. TRACE_INFO("sendto sent %i bytes out of %i. Retry...", ret, sizeof (rct_req));
  1309. continue;
  1310. }
  1311. /* Set "access bits" in request IOCTL code to use local settings ie. FILE_WRITE_ACCESS */
  1312. SET_IOCTL_ACCESS_BITS_TO_LOCAL(rct_req.ioctrl)
  1313. WLBS_RESPONSE callbackResp;
  1314. for (num_recvs = 0; num_recvs < IOCTL_REMOTE_RECV_RETRIES; num_recvs ++)
  1315. {
  1316. //
  1317. // Receive a remote control reply
  1318. //
  1319. ZeroMemory((PVOID)&rct_rep, sizeof(IOCTL_REMOTE_HDR));
  1320. ret = recv (sock, (PCHAR) & rct_rep, sizeof (rct_rep), 0);
  1321. if (ret == SOCKET_ERROR)
  1322. {
  1323. dwStatus = WSAGetLastError();
  1324. if (dwStatus == WSAEWOULDBLOCK)
  1325. {
  1326. TRACE_INFO("recv is blocking. Sleep %d then retry...", timeout);
  1327. Sleep (timeout);
  1328. continue;
  1329. }
  1330. else if (dwStatus == WSAECONNRESET)
  1331. {
  1332. //
  1333. // Remote control is disabled
  1334. //
  1335. TRACE_INFO("recv failed with connection reset. Check for more receives");
  1336. continue;
  1337. }
  1338. else
  1339. {
  1340. TRACE_CRIT("recv failed with 0x%x", dwStatus);
  1341. goto end;
  1342. }
  1343. }
  1344. if (ret != sizeof (rct_rep))
  1345. {
  1346. TRACE_INFO("recv received %i bytes out of %i. Sleep %d and try again...", ret, sizeof (rct_rep), timeout);
  1347. Sleep (timeout);
  1348. continue;
  1349. }
  1350. if (rct_rep . cluster != trg_addr)
  1351. {
  1352. TRACE_INFO("recv received from unintended party %d. Sleep %d and try again...", trg_addr, timeout);
  1353. Sleep (timeout);
  1354. continue;
  1355. }
  1356. if (rct_rep . code != IOCTL_REMOTE_CODE)
  1357. {
  1358. TRACE_INFO("recv received unexpected code type. Sleep %d and try again...", timeout);
  1359. Sleep (timeout);
  1360. continue;
  1361. }
  1362. if (rct_rep . id != rct_req . id)
  1363. {
  1364. TRACE_INFO("recv received unexpected message id. Sleep %d and try again...", timeout);
  1365. Sleep (timeout);
  1366. continue;
  1367. }
  1368. if (rct_rep . host > WLBS_MAX_HOSTS || rct_rep . host == 0 )
  1369. {
  1370. TRACE_INFO("recv received illegal host id %ul. Sleep %d and try again...", rct_rep . host, timeout);
  1371. Sleep (timeout);
  1372. continue;
  1373. }
  1374. /* Set "access bits" in reply IOCTL code to use local settings ie. FILE_WRITE_ACCESS */
  1375. SET_IOCTL_ACCESS_BITS_TO_LOCAL(rct_rep.ioctrl)
  1376. //
  1377. // Set the pointer to the host name if the host says it provided one
  1378. // Do this here because the flags checking would otherwise need to be done in
  1379. // several places with a NULL pointer passed when hostname is not provided.
  1380. // Instead, we can do the check once use the pointer filled here.
  1381. //
  1382. pszTmpHostName = NULL;
  1383. if (rct_rep.options.query.flags & NLB_OPTIONS_QUERY_HOSTNAME)
  1384. {
  1385. pszTmpHostName = rct_rep.options.query.hostname;
  1386. pszTmpHostName[CVY_MAX_HOST_NAME] = UNICODE_NULL; // Just in case the host name is not null terminated, do it.
  1387. }
  1388. if (! responded [rct_rep . host - 1]
  1389. || !FindHostInList(rct_rep . host, rct_rep . addr, pszTmpHostName, respondedHosts, hosts))
  1390. {
  1391. if (hosts < WLBS_MAX_HOSTS)
  1392. {
  1393. AddHostToList(rct_rep . host, rct_rep . addr, pszTmpHostName, respondedHosts, hosts);
  1394. pout_bufp [hosts] = rct_rep . ctrl;
  1395. if (hosts < * nump && pcvy_resp != NULL)
  1396. {
  1397. pcvy_resp [hosts] . id = rct_rep . host;
  1398. pcvy_resp [hosts] . address = rct_rep . addr;
  1399. switch (rct_req.ioctrl) {
  1400. case IOCTL_CVY_QUERY:
  1401. pcvy_resp[hosts].status = MapStateFromDriverToApi(rct_rep.ctrl.data.query.state);
  1402. pcvy_resp[hosts].options.query.flags = rct_rep.options.query.flags;
  1403. if (NULL != pszTmpHostName)
  1404. {
  1405. wcsncpy(pcvy_resp[hosts].options.query.hostname, pszTmpHostName, CVY_MAX_HOST_NAME);
  1406. // Terminate the end of the destination with a NULL. If source string was shorter than count specified
  1407. // this will be a no-op but it's simpler than checking if we need to do it. Worst case we overwrite a NULL with a NULL.
  1408. pcvy_resp[hosts].options.query.hostname[CVY_MAX_HOST_NAME] = L'\0';
  1409. }
  1410. if (NULL != pfnQueryCallBack)
  1411. {
  1412. CopyMemory((PVOID)&callbackResp, (PVOID)&pcvy_resp[hosts], sizeof(WLBS_RESPONSE));
  1413. (*pfnQueryCallBack)(&callbackResp);
  1414. }
  1415. break;
  1416. case IOCTL_CVY_QUERY_FILTER:
  1417. pcvy_resp[hosts].status = MapStateFromDriverToApi(rct_rep.ctrl.data.query.state);
  1418. pcvy_resp[hosts].options.state.flags = rct_rep.options.common.state.flags;
  1419. pcvy_resp[hosts].options.state.filter = rct_rep.options.common.state.filter;
  1420. break;
  1421. case IOCTL_CVY_QUERY_PORT_STATE:
  1422. pcvy_resp[hosts].status = MapStateFromDriverToApi(rct_rep.ctrl.data.query.state);
  1423. pcvy_resp[hosts].options.state.flags = rct_rep.options.common.state.flags;
  1424. pcvy_resp[hosts].options.state.port = rct_rep.options.common.state.port;
  1425. break;
  1426. default:
  1427. pcvy_resp[hosts].status = MapStateFromDriverToApi(rct_rep.ctrl.ret_code);
  1428. break;
  1429. }
  1430. }
  1431. else
  1432. {
  1433. // We only log this event if the user wants the response and the response is too big...
  1434. if (pcvy_resp != NULL)
  1435. {
  1436. TRACE_INFO("recv has received %d responses but the caller can only accept %d. ", hosts, *nump);
  1437. }
  1438. }
  1439. hosts ++;
  1440. }
  1441. }
  1442. responded [rct_rep . host - 1] = TRUE;
  1443. heard = TRUE;
  1444. if (hst_addr != WLBS_ALL_HOSTS)
  1445. {
  1446. dwStatus = WLBS_OK;
  1447. goto end;
  1448. }
  1449. }
  1450. }
  1451. dwStatus = WLBS_OK;
  1452. if (! heard)
  1453. {
  1454. dwStatus = WLBS_TIMEOUT;
  1455. }
  1456. end:
  1457. * nump = hosts;
  1458. if (sock != INVALID_SOCKET)
  1459. {
  1460. //
  1461. // We never return the status of closesocket() because:
  1462. // 1) If everything was a success until now, we have the info
  1463. // the caller needs and we must return status="WLBS_OK"
  1464. // so that the caller can get the data.
  1465. // 2) If we've failed somewhere above, then that error is more
  1466. // important to report than the reason for the closesocket()
  1467. // failure.
  1468. //
  1469. (VOID) closesocket(sock);
  1470. }
  1471. TRACE_VERB("<- returning 0x%x", dwStatus);
  1472. return dwStatus;
  1473. }
  1474. //+----------------------------------------------------------------------------
  1475. //
  1476. // Function: GetNextHostInHostMap
  1477. //
  1478. // Description: Used by WlbsGetClusterMembers, it traverses a 32-bit host map
  1479. // to find the next host after the one input.
  1480. //
  1481. // Arguments: ULONG host_id - input host id, range 1-32. We look for a host after this in the map
  1482. // ULONG host_map - input 32-bit map of hosts
  1483. //
  1484. // Returns: ULONG - the next host in the map (sequentially). If none, then
  1485. // IOCTL_NO_SUCH_HOST is returned.
  1486. //
  1487. // History: ChrisDar, Created 2002 May 21
  1488. //
  1489. // Notes: The user passes a host id with range 1-32, but the map uses bit 0 for host 1.
  1490. // This makes this function a little tricky.
  1491. //+----------------------------------------------------------------------------
  1492. ULONG GetNextHostInHostMap(ULONG host_id, ULONG host_map)
  1493. {
  1494. ULONG next_host_id = IOCTL_NO_SUCH_HOST;
  1495. /* The map encodes the first host in bit 0, hence 0-31 based range. Use this in the search */
  1496. ULONG map_host_id = host_id - 1;
  1497. /* This is illegal input data */
  1498. ASSERT(map_host_id < CVY_MAX_HOSTS); // 0-based range
  1499. if (map_host_id >= CVY_MAX_HOSTS)
  1500. {
  1501. TRACE_CRIT("%!FUNC! illegal host id [1-32] %d", map_host_id+1);
  1502. goto end;
  1503. }
  1504. //
  1505. // This is an early bail-out because the "get next" semantics of this function imply that the input
  1506. // host id will not be the largest possible.
  1507. // NOTE: ChrisDar: 2002 May 23. This check was added because host_map >>= 32 leaves host_map unchanged
  1508. // in test code. That will cause an assert in the code below as we expect host_map = 0 in this
  1509. // case.
  1510. //
  1511. if (map_host_id >= CVY_MAX_HOSTS - 1)
  1512. {
  1513. TRACE_VERB("%!FUNC! input host id [1-32] %d is already the largest possible. No need to search for next host in map.", map_host_id+1);
  1514. goto end;
  1515. }
  1516. //
  1517. // Shift the host_map forward to the position just beyond host_id (ignore whether it is set in the map)
  1518. //
  1519. map_host_id++;
  1520. host_map >>= map_host_id;
  1521. //
  1522. // Find the next host in the map, if any.
  1523. //
  1524. while (host_map != 0)
  1525. {
  1526. ASSERT(map_host_id < CVY_MAX_HOSTS);
  1527. if ((host_map & 0x1) == 1)
  1528. {
  1529. /* Return a host id that has range 1-32 */
  1530. next_host_id = map_host_id + 1;
  1531. break;
  1532. }
  1533. host_map >>= 1;
  1534. map_host_id++;
  1535. }
  1536. end:
  1537. return next_host_id;
  1538. }
  1539. //+----------------------------------------------------------------------------
  1540. //
  1541. // Function: WlbsGetSpecifiedOrAllClusterMembers
  1542. //
  1543. // Description: Wrapper around WlbsRemoteControl() for a query
  1544. //
  1545. // Arguments: in Adapter GUID,
  1546. // in host id (pass IOCTL_FIRST_HOST if interested in all cluster member)
  1547. // out for number of hosts and
  1548. // out for information requested. All must be valid pointers.
  1549. //
  1550. // Returns: Status Code
  1551. //
  1552. // History: KarthicN, Created 2002, July 12 - Added support for querying a specific
  1553. // cluster member and changed name from
  1554. // WlbsGetClusterMembers.
  1555. //
  1556. //+----------------------------------------------------------------------------
  1557. DWORD WlbsGetSpecifiedOrAllClusterMembers
  1558. (
  1559. IN const GUID * pAdapterGuid,
  1560. IN ULONG host_id,
  1561. OUT DWORD * pNumHosts,
  1562. OUT PWLBS_RESPONSE pResponse
  1563. )
  1564. {
  1565. TRACE_VERB("->");
  1566. DWORD status = WLBS_OK;
  1567. HANDLE hNlb = INVALID_HANDLE_VALUE;
  1568. ULONG ulNumHosts = 0;
  1569. //
  1570. // We retrieve cached identitiy information for the caller
  1571. //
  1572. const LONG ioctl = IOCTL_CVY_QUERY_MEMBER_IDENTITY;
  1573. ASSERT(pNumHosts != NULL);
  1574. ASSERT(pResponse != NULL);
  1575. //
  1576. // Open a handle to the driver
  1577. //
  1578. hNlb = WlbsOpen();
  1579. if (hNlb == INVALID_HANDLE_VALUE)
  1580. {
  1581. TRACE_CRIT(L"!FUNC! failed to open handle to driver. Exiting...");
  1582. *pNumHosts = 0;
  1583. status = WLBS_INIT_ERROR;
  1584. goto end;
  1585. }
  1586. bool first_iter = true;
  1587. /* Host IDs are 1-32 */
  1588. do
  1589. {
  1590. IOCTL_CVY_BUF in_buf;
  1591. IOCTL_CVY_BUF out_buf;
  1592. IOCTL_LOCAL_OPTIONS options;
  1593. ZeroMemory(&in_buf, sizeof(in_buf));
  1594. ZeroMemory(&options, sizeof(options));
  1595. options.identity.host_id = host_id;
  1596. status = WlbsLocalControl (hNlb, *pAdapterGuid, ioctl, &in_buf, &out_buf, &options);
  1597. if (status != WLBS_OK || out_buf.ret_code != IOCTL_CVY_OK)
  1598. {
  1599. TRACE_CRIT(L"%!FUNC! IOCTL call failed. Status = 0x%x", status);
  1600. break;
  1601. }
  1602. if (options.identity.cached_entry.host == IOCTL_NO_SUCH_HOST)
  1603. {
  1604. TRACE_INFO(L"%!FUNC! Identity cache has been traversed");
  1605. break;
  1606. }
  1607. if (*pNumHosts <= ulNumHosts)
  1608. {
  1609. TRACE_INFO(L"%!FUNC! No more room in output array");
  1610. break;
  1611. }
  1612. pResponse[ulNumHosts].id = options.identity.cached_entry.host;
  1613. pResponse[ulNumHosts].address = options.identity.cached_entry.ded_ip_addr;
  1614. HRESULT hr = StringCchCopy(pResponse[ulNumHosts].options.identity.fqdn,
  1615. ASIZECCH(pResponse[ulNumHosts].options.identity.fqdn),
  1616. options.identity.cached_entry.fqdn
  1617. );
  1618. ulNumHosts++;
  1619. ASSERT(hr == S_OK); // This shouldn't happen since we allocated a buffer large enough to handle any legal fqdn
  1620. if (hr != S_OK)
  1621. {
  1622. //
  1623. // Not nice, but no problem since the API truncates the name. But report it so we can fix the logic error.
  1624. //
  1625. TRACE_CRIT(L"%!FUNC! fqdn too long to fit into destination buffer");
  1626. }
  1627. // If a specific host id is passed, break out of the loop and return
  1628. if (first_iter)
  1629. {
  1630. if (host_id != IOCTL_FIRST_HOST)
  1631. break;
  1632. first_iter = false;
  1633. }
  1634. /* Check if we need to IOCTL for more cache entries */
  1635. host_id = GetNextHostInHostMap(options.identity.cached_entry.host, options.identity.host_map);
  1636. } while (host_id != IOCTL_NO_SUCH_HOST);
  1637. *pNumHosts = ulNumHosts;
  1638. (VOID) CloseHandle(hNlb);
  1639. end:
  1640. TRACE_VERB("<- returning %d", status);
  1641. return status;
  1642. }
  1643. //+----------------------------------------------------------------------------
  1644. //
  1645. // Function: WlbsGetClusterMembers
  1646. //
  1647. // Description: Wrapper around WlbsGetSpecifiedOrAllClusterMembers() for querying
  1648. // all cluster members
  1649. //
  1650. // Arguments: in Adapter GUID, out for number of hosts and
  1651. // out for information requested. All must be valid pointers.
  1652. //
  1653. // Returns: Status Code
  1654. //
  1655. // History: ChrisDar, Created 2002 Jan 11
  1656. // KarthicN, Edited 2002, July 12 - Moved most of the code to new
  1657. // function WlbsGetSpecifiedOrAllClusterMembers
  1658. //
  1659. //+----------------------------------------------------------------------------
  1660. DWORD WINAPI WlbsGetClusterMembers
  1661. (
  1662. IN const GUID * pAdapterGuid,
  1663. OUT DWORD * pNumHosts,
  1664. OUT PWLBS_RESPONSE pResponse
  1665. )
  1666. {
  1667. return WlbsGetSpecifiedOrAllClusterMembers(pAdapterGuid, IOCTL_FIRST_HOST, pNumHosts, pResponse);
  1668. }
  1669. //+----------------------------------------------------------------------------
  1670. //
  1671. // Function: WlbsGetSpecifiedClusterMember
  1672. //
  1673. // Description: Wrapper around WlbsGetSpecifiedOrAllClusterMembers() to query
  1674. // the specified cluster member
  1675. //
  1676. // Arguments: in Adapter GUID, in host_id,
  1677. // out for information requested. All must be valid pointers.
  1678. //
  1679. // Returns: Status Code
  1680. //
  1681. // History: KarthicN, Created 2002 July 12
  1682. //
  1683. //+----------------------------------------------------------------------------
  1684. DWORD WINAPI WlbsGetSpecifiedClusterMember
  1685. (
  1686. IN const GUID * pAdapterGuid,
  1687. IN ULONG host_id,
  1688. OUT PWLBS_RESPONSE pResponse
  1689. )
  1690. {
  1691. DWORD NumHosts = 1;
  1692. return WlbsGetSpecifiedOrAllClusterMembers(pAdapterGuid, host_id, &NumHosts, pResponse);
  1693. }
  1694. //+----------------------------------------------------------------------------
  1695. //
  1696. // Function: WlbsLocalControl
  1697. //
  1698. // Description: Send DeviceIoControl to local driver
  1699. //
  1700. // Arguments: HANDLE hDevice -
  1701. // const GUID& AdapterGuid - the guid of the adapter
  1702. // LONG ioctl -
  1703. // PIOCTL_CVY_BUF in_bufp -
  1704. // PIOCTL_CVY_BUF out_bufp -
  1705. //
  1706. // Returns: DWORD -
  1707. //
  1708. // History: fengsun Created Header 3/9/00
  1709. //
  1710. //+----------------------------------------------------------------------------
  1711. DWORD WlbsLocalControl
  1712. (
  1713. HANDLE hDevice,
  1714. const GUID& AdapterGuid,
  1715. LONG ioctl,
  1716. PIOCTL_CVY_BUF in_bufp,
  1717. PIOCTL_CVY_BUF out_bufp,
  1718. PIOCTL_LOCAL_OPTIONS optionsp
  1719. )
  1720. {
  1721. TRACE_VERB("->%!FUNC! ioctl %i", ioctl);
  1722. BOOLEAN res;
  1723. DWORD act;
  1724. IOCTL_LOCAL_HDR inBuf;
  1725. IOCTL_LOCAL_HDR outBuf;
  1726. HRESULT hresult;
  1727. WCHAR szGuid[128];
  1728. ZeroMemory((PVOID)&inBuf, sizeof(IOCTL_LOCAL_HDR));
  1729. ZeroMemory((PVOID)&outBuf, sizeof(IOCTL_LOCAL_HDR));
  1730. if (StringFromGUID2(AdapterGuid, szGuid, sizeof(szGuid)/ sizeof(szGuid[0])) == 0)
  1731. {
  1732. TRACE_CRIT("%!FUNC! buffer size %d is too small to hold guid string", sizeof(szGuid)/ sizeof(szGuid[0]));
  1733. // This check was added for tracing. No abort was done previously on error, so don't do so now.
  1734. }
  1735. hresult = StringCbCopy(inBuf.device_name, sizeof(inBuf.device_name), L"\\DEVICE\\");
  1736. if (FAILED(hresult))
  1737. {
  1738. TRACE_CRIT("%!FUNC! string copy failed, Error code : 0x%x", HRESULT_CODE(hresult));
  1739. // This check was added for tracing. No abort was done previously on error, so don't do so now.
  1740. }
  1741. hresult = StringCbCat(inBuf.device_name, sizeof(inBuf.device_name), szGuid);
  1742. if (FAILED(hresult))
  1743. {
  1744. TRACE_CRIT("%!FUNC! string append failed, Error code : 0x%x", HRESULT_CODE(hresult));
  1745. // This check was added for tracing. No abort was done previously on error, so don't do so now.
  1746. }
  1747. inBuf.ctrl = *in_bufp;
  1748. if (optionsp)
  1749. inBuf.options = *optionsp;
  1750. res = (BOOLEAN) DeviceIoControl (hDevice, ioctl, &inBuf, sizeof (inBuf),
  1751. &outBuf, sizeof (outBuf), & act, NULL);
  1752. if (! res || act != sizeof (outBuf))
  1753. {
  1754. DWORD dwStatus = GetLastError();
  1755. TRACE_CRIT("%!FUNC! call to nlb driver failed with %d", dwStatus);
  1756. TRACE_VERB("<-%!FUNC! returning %d", WLBS_IO_ERROR);
  1757. return WLBS_IO_ERROR;
  1758. }
  1759. /* We have verified that the IOCTL succeeded and the output buffer is the right size. We can now look
  1760. into the output buffer. */
  1761. if (outBuf.ctrl.ret_code == IOCTL_CVY_NOT_FOUND)
  1762. {
  1763. TRACE_INFO("%!FUNC! call to nlb driver returned IOCTL_CVY_NOT_FOUND");
  1764. TRACE_VERB("<-%!FUNC! returning %d", WLBS_IO_ERROR);
  1765. return WLBS_IO_ERROR;
  1766. }
  1767. *out_bufp = outBuf.ctrl;
  1768. if (optionsp)
  1769. *optionsp = outBuf.options;
  1770. TRACE_VERB("<-%!FUNC! returning %d", WLBS_OK);
  1771. return WLBS_OK;
  1772. }
  1773. //+----------------------------------------------------------------------------
  1774. //
  1775. // Function: NotifyDriverConfigChanges
  1776. //
  1777. // Description: Notify wlbs driver to pick up configuration changes from
  1778. // registry
  1779. //
  1780. // Arguments: HANDLE hDeviceWlbs - The WLBS driver device handle
  1781. // const GUID& - AdapterGuid Adapter guid
  1782. //
  1783. //
  1784. // Returns: DWORD - Win32 Error code
  1785. //
  1786. // History: fengsun Created Header 2/3/00
  1787. //
  1788. //+----------------------------------------------------------------------------
  1789. DWORD WINAPI NotifyDriverConfigChanges(HANDLE hDeviceWlbs, const GUID& AdapterGuid)
  1790. {
  1791. TRACE_VERB("->%!FUNC!");
  1792. LONG status;
  1793. IOCTL_CVY_BUF in_buf;
  1794. IOCTL_CVY_BUF out_buf;
  1795. status = WlbsLocalControl (hDeviceWlbs, AdapterGuid, IOCTL_CVY_RELOAD, & in_buf, & out_buf, NULL);
  1796. if (status == WLBS_IO_ERROR)
  1797. {
  1798. TRACE_CRIT("%!FUNC! call to do local control failed with %d", status);
  1799. return status;
  1800. }
  1801. if (out_buf.ret_code == IOCTL_CVY_BAD_PARAMS)
  1802. {
  1803. TRACE_CRIT("%!FUNC! call to do local control failed due to bad parameters");
  1804. TRACE_VERB("<-%!FUNC! returning %d", WLBS_BAD_PARAMS);
  1805. return WLBS_BAD_PARAMS;
  1806. }
  1807. TRACE_VERB("<-%!FUNC! returning %d", ERROR_SUCCESS);
  1808. return ERROR_SUCCESS;
  1809. }
  1810. //+----------------------------------------------------------------------------
  1811. //
  1812. // Function: CWlbsControl::WlbsRemoteControl
  1813. //
  1814. // Description: Send a remote control packet
  1815. //
  1816. // Arguments: ONG ioctl -
  1817. // PIOCTL_CVY_BUF pin_bufp -
  1818. // PIOCTL_CVY_BUF pout_bufp -
  1819. // PWLBS_RESPONSE pcvy_resp -
  1820. // PDWORD nump -
  1821. // DWORD trg_addr -
  1822. // DWORD hst_addr
  1823. // PIOCTL_REMOTE_OPTIONS optionsp -
  1824. // PFN_QUERY_CALLBACK pfnQueryCallBack - function pointer for callback.
  1825. // Used only for remote queries.
  1826. //
  1827. // Returns: DWORD -
  1828. //
  1829. // History: fengsun Created Header 1/25/00
  1830. // chrisdar 07.31.01 Added optional callback function pointer for
  1831. // query. Allows user to get results from query
  1832. // as the hosts reply rather than waiting for the
  1833. // timer to expire. This recovers NT4 behavior.
  1834. // chrisdar 08.06.01 Changed definition of a unique host from host ID
  1835. // to host ID, host IP (DIP) and host name. Makes
  1836. // multiple hosts using the same host ID apparent in
  1837. // queries and the like.
  1838. //
  1839. //+----------------------------------------------------------------------------
  1840. DWORD CWlbsControl::WlbsRemoteControl
  1841. (
  1842. LONG ioctl,
  1843. PIOCTL_CVY_BUF pin_bufp,
  1844. PIOCTL_CVY_BUF pout_bufp,
  1845. PWLBS_RESPONSE pcvy_resp,
  1846. PDWORD nump,
  1847. DWORD trg_addr,
  1848. DWORD hst_addr,
  1849. PIOCTL_REMOTE_OPTIONS optionsp,
  1850. PFN_QUERY_CALLBACK pfnQueryCallBack
  1851. )
  1852. {
  1853. DWORD timeout;
  1854. WORD port;
  1855. DWORD dst_addr;
  1856. DWORD passw;
  1857. BOOL fIsLocal = TRUE;
  1858. DWORD i;
  1859. timeout = m_def_timeout;
  1860. port = m_def_port;
  1861. dst_addr = m_def_dst_addr;
  1862. passw = m_def_passw;
  1863. // LOCK(m_lock);
  1864. //
  1865. // Find parameters for the cluster
  1866. //
  1867. for (i = 0; i < WLBS_MAX_CLUSTERS; i ++)
  1868. {
  1869. if (m_cluster_params [i] . cluster == trg_addr)
  1870. break;
  1871. }
  1872. if (i < WLBS_MAX_CLUSTERS)
  1873. {
  1874. timeout = m_cluster_params [i] . timeout;
  1875. port = m_cluster_params [i] . port;
  1876. dst_addr = m_cluster_params [i] . dest;
  1877. passw = m_cluster_params [i] . passw;
  1878. }
  1879. CWlbsCluster* pCluster = GetClusterFromIp(trg_addr);
  1880. if (pCluster == NULL)
  1881. {
  1882. fIsLocal = FALSE;
  1883. TRACE_INFO("%!FUNC! cluster instance not found");
  1884. }
  1885. /*
  1886. if (pCluster)
  1887. {
  1888. //
  1889. // Always uses password in registry for local cluster
  1890. //
  1891. passw = pCluster->GetPassword();
  1892. }
  1893. */
  1894. // UNLOCK(m_lock);
  1895. return WlbsRemoteControlInternal (ioctl, pin_bufp, pout_bufp, pcvy_resp, nump, trg_addr, hst_addr, optionsp, fIsLocal, pfnQueryCallBack, timeout, port, dst_addr, passw);
  1896. }
  1897. //+----------------------------------------------------------------------------
  1898. //
  1899. // Function: CWlbsControl::WlbsQuery
  1900. //
  1901. // Description:
  1902. // This function is for internal use only and assumes that the caller
  1903. // has initialized pCluster.
  1904. //
  1905. // Arguments: CWlbsCluster* pCluster -
  1906. // DWORD host -
  1907. // PWLBS_RESPONSE response -
  1908. // PDWORD num_hosts -
  1909. // PDWORD host_map -
  1910. // PFN_QUERY_CALLBACK pfnQueryCallBack
  1911. //
  1912. // Returns: DWORD -
  1913. //
  1914. // History: fengsun Created Header 1/25/00
  1915. // chrisdar 07.31.01 Modified interface to replace the reserved
  1916. // PVOID with an optional callback function pointer.
  1917. // This is to provide wlbs.exe with host status as
  1918. // it arrives.
  1919. //
  1920. //+----------------------------------------------------------------------------
  1921. DWORD CWlbsControl::WlbsQuery
  1922. (
  1923. CWlbsCluster* pCluster,
  1924. DWORD host,
  1925. PWLBS_RESPONSE response,
  1926. PDWORD num_hosts,
  1927. PDWORD host_map,
  1928. PFN_QUERY_CALLBACK pfnQueryCallBack
  1929. )
  1930. {
  1931. TRACE_VERB("->%!FUNC! host 0x%lx", host);
  1932. LONG ioctl = IOCTL_CVY_QUERY;
  1933. DWORD status;
  1934. IOCTL_CVY_BUF in_buf;
  1935. ASSERT(pCluster != NULL);
  1936. DWORD dwInitResult = GetInitResult();
  1937. if (dwInitResult == WLBS_INIT_ERROR)
  1938. {
  1939. TRACE_CRIT("%!FUNC! failed checking GetInitResult");
  1940. TRACE_VERB("<-%!FUNC! returning %d", dwInitResult);
  1941. return dwInitResult;
  1942. }
  1943. /* The following condition is to take care of the case when num_hosts is null
  1944. * and host_map contains some junk value. This could crash this function. */
  1945. if (num_hosts == NULL || *num_hosts == 0)
  1946. {
  1947. TRACE_INFO("%!FUNC! caller does not want query results returned");
  1948. response = NULL;
  1949. }
  1950. if (IsLocalHost(pCluster, host))
  1951. {
  1952. IOCTL_CVY_BUF out_buf;
  1953. IOCTL_LOCAL_OPTIONS localOptions;
  1954. status = WlbsLocalControl (m_hdl, pCluster->GetAdapterGuid(),
  1955. ioctl, & in_buf, & out_buf, &localOptions);
  1956. if (status == WLBS_IO_ERROR)
  1957. {
  1958. TRACE_CRIT("%!FUNC! local control call failed with %d", status);
  1959. TRACE_VERB("<-%!FUNC! returning %d", status);
  1960. return status;
  1961. }
  1962. if (host_map != NULL)
  1963. * host_map = out_buf . data . query . host_map;
  1964. if (response != NULL)
  1965. {
  1966. response [0] . id = out_buf . data . query . host_id;
  1967. response [0] . address = 0;
  1968. response [0] . status = MapStateFromDriverToApi (out_buf . data . query . state);
  1969. /* Fill in the optional query information. */
  1970. response[0].options.query.flags = localOptions.query.flags;
  1971. response[0].options.query.NumConvergences = localOptions.query.NumConvergences;
  1972. response[0].options.query.LastConvergence = localOptions.query.LastConvergence;
  1973. }
  1974. if (num_hosts != NULL)
  1975. * num_hosts = 1;
  1976. status = MapStateFromDriverToApi (out_buf . data . query . state);
  1977. TRACE_INFO("%!FUNC! local query returned %d", status);
  1978. }
  1979. else
  1980. {
  1981. status = RemoteQuery(pCluster->GetClusterIp(),
  1982. host, response, num_hosts, host_map, pfnQueryCallBack);
  1983. TRACE_INFO("%!FUNC! remote query returned %d", status);
  1984. }
  1985. TRACE_VERB("<-%!FUNC! returning %d", status);
  1986. return status;
  1987. }
  1988. //+----------------------------------------------------------------------------
  1989. //
  1990. // Function: CWlbsControl::WlbsQuery
  1991. //
  1992. // Description:
  1993. //
  1994. // Arguments: WORD cluster -
  1995. // DWORD host -
  1996. // PWLBS_RESPONSE response -
  1997. // PDWORD num_hosts -
  1998. // PDWORD host_map -
  1999. // PFN_QUERY_CALLBACK pfnQueryCallBack
  2000. //
  2001. // Returns: DWORD -
  2002. //
  2003. // History: fengsun Created Header 1/25/00
  2004. // chrisdar 07.31.01 Modified interface to replace the reserved
  2005. // PVOID with an optional callback function pointer.
  2006. // This is to provide wlbs.exe with host status as
  2007. // it arrives.
  2008. //
  2009. //+----------------------------------------------------------------------------
  2010. DWORD CWlbsControl::WlbsQuery
  2011. (
  2012. DWORD cluster,
  2013. DWORD host,
  2014. PWLBS_RESPONSE response,
  2015. PDWORD num_hosts,
  2016. PDWORD host_map,
  2017. PFN_QUERY_CALLBACK pfnQueryCallBack
  2018. )
  2019. {
  2020. TRACE_VERB("->%!FUNC! cluster=0x%lx, host=0x%lx", cluster, host);
  2021. DWORD ret;
  2022. DWORD dwInitResult = GetInitResult();
  2023. if (dwInitResult == WLBS_INIT_ERROR)
  2024. {
  2025. TRACE_INFO("%!FUNC! failed checking GetInitResult with %d", dwInitResult);
  2026. ret = dwInitResult;
  2027. goto end;
  2028. }
  2029. if (cluster == WLBS_LOCAL_CLUSTER && dwInitResult == WLBS_REMOTE_ONLY)
  2030. {
  2031. TRACE_INFO("%!FUNC! can't query local cluster; this host is configured for remote only");
  2032. ret = dwInitResult;
  2033. goto end;
  2034. }
  2035. CWlbsCluster* pCluster = GetClusterFromIpOrIndex(cluster);
  2036. if (pCluster == NULL)
  2037. {
  2038. ret = RemoteQuery(cluster, host, response, num_hosts, host_map, pfnQueryCallBack);
  2039. TRACE_INFO("%!FUNC! remote query returned %d", ret);
  2040. goto end;
  2041. }
  2042. else
  2043. {
  2044. ret = WlbsQuery(pCluster, host, response, num_hosts, host_map, pfnQueryCallBack);
  2045. TRACE_INFO("%!FUNC! local query returned %d", ret);
  2046. goto end;
  2047. }
  2048. end:
  2049. TRACE_VERB("<-%!FUNC! return %d", ret);
  2050. return ret;
  2051. }
  2052. //+----------------------------------------------------------------------------
  2053. //
  2054. // Function: CWlbsControl::RemoteQuery
  2055. //
  2056. // Description:
  2057. //
  2058. // Arguments: DWORD cluster -
  2059. // DWORD host -
  2060. // PWLBS_RESPONSE response -
  2061. // PDWORD num_hosts -
  2062. // PDWORD host_map -
  2063. //
  2064. // Returns: DWORD -
  2065. //
  2066. // History: fengsun Created Header 1/25/00
  2067. //
  2068. //+----------------------------------------------------------------------------
  2069. DWORD CWlbsControl::RemoteQuery
  2070. (
  2071. DWORD cluster,
  2072. DWORD host,
  2073. PWLBS_RESPONSE response,
  2074. PDWORD num_hosts,
  2075. PDWORD host_map,
  2076. PFN_QUERY_CALLBACK pfnQueryCallBack
  2077. )
  2078. {
  2079. TRACE_VERB("->%!FUNC! cluster 0x%lx, host 0x%lx", cluster, host);
  2080. LONG ioctl = IOCTL_CVY_QUERY;
  2081. DWORD status;
  2082. IOCTL_CVY_BUF in_buf;
  2083. IOCTL_CVY_BUF out_buf [WLBS_MAX_HOSTS];
  2084. DWORD hosts;
  2085. DWORD hmap = 0;
  2086. DWORD active;
  2087. DWORD i;
  2088. BOOLEAN bIsMember = IsClusterMember(cluster);
  2089. IOCTL_REMOTE_OPTIONS options;
  2090. DWORD dwInitResult = GetInitResult();
  2091. if (dwInitResult == WLBS_LOCAL_ONLY)
  2092. {
  2093. TRACE_CRIT("%!FUNC! only local actions may be performed");
  2094. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2095. return dwInitResult;
  2096. }
  2097. if (num_hosts != NULL)
  2098. hosts = * num_hosts;
  2099. else
  2100. hosts = 0;
  2101. /* Reset the flags. */
  2102. options.query.flags = 0;
  2103. /* If I am myself a member of the target cluster, then set the query cluster flags appropriately. */
  2104. if (bIsMember)
  2105. options.query.flags |= NLB_OPTIONS_QUERY_CLUSTER_MEMBER;
  2106. status = WlbsRemoteControl (ioctl, & in_buf, out_buf, response, & hosts,
  2107. cluster, host, &options, pfnQueryCallBack);
  2108. if (status >= WSABASEERR || status == WLBS_TIMEOUT)
  2109. {
  2110. TRACE_CRIT("%!FUNC! remote query failed with %d", status);
  2111. if (num_hosts != NULL)
  2112. * num_hosts = 0;
  2113. TRACE_VERB("<-%!FUNC! return %d", status);
  2114. return status;
  2115. }
  2116. if (host == WLBS_ALL_HOSTS)
  2117. {
  2118. for (status = WLBS_STOPPED, active = 0, i = 0; i < hosts; i ++)
  2119. {
  2120. switch (MapStateFromDriverToApi (out_buf [i] . data . query . state))
  2121. {
  2122. case WLBS_SUSPENDED:
  2123. if (status == WLBS_STOPPED)
  2124. status = WLBS_SUSPENDED;
  2125. break;
  2126. case WLBS_CONVERGING:
  2127. if (status != WLBS_BAD_PASSW)
  2128. status = WLBS_CONVERGING;
  2129. break;
  2130. case WLBS_DRAINING:
  2131. if (status == WLBS_STOPPED)
  2132. status = WLBS_DRAINING;
  2133. break;
  2134. case WLBS_CONVERGED:
  2135. if (status != WLBS_CONVERGING && status != WLBS_BAD_PASSW)
  2136. status = WLBS_CONVERGED;
  2137. hmap = out_buf [i] . data . query . host_map;
  2138. active ++;
  2139. break;
  2140. case WLBS_BAD_PASSW:
  2141. status = WLBS_BAD_PASSW;
  2142. break;
  2143. case WLBS_DEFAULT:
  2144. if (status != WLBS_CONVERGING && status != WLBS_BAD_PASSW)
  2145. status = WLBS_CONVERGED;
  2146. hmap = out_buf [i] . data . query . host_map;
  2147. active ++;
  2148. break;
  2149. case WLBS_STOPPED:
  2150. default:
  2151. break;
  2152. }
  2153. }
  2154. if (status == WLBS_CONVERGED)
  2155. status = active;
  2156. TRACE_INFO("%!FUNC! result on all hosts is %d", status);
  2157. }
  2158. else
  2159. {
  2160. status = MapStateFromDriverToApi (out_buf [0] . data . query . state);
  2161. hmap = out_buf [0] . data . query . host_map;
  2162. TRACE_INFO("%!FUNC! result on host is %d", status);
  2163. }
  2164. if (host_map != NULL)
  2165. * host_map = hmap;
  2166. if (num_hosts != NULL)
  2167. * num_hosts = hosts;
  2168. TRACE_VERB("<-%!FUNC! return %d", status);
  2169. return status;
  2170. }
  2171. //+----------------------------------------------------------------------------
  2172. //
  2173. // Function: CWlbsControl::WlbsSuspend
  2174. //
  2175. // Description:
  2176. //
  2177. // Arguments: WORD cluster -
  2178. // DWORD host -
  2179. // PWLBS_RESPONSE response -
  2180. // PDWORD num_hosts
  2181. //
  2182. // Returns: DWORD -
  2183. //
  2184. // History: fengsun Created Header 1/25/00
  2185. //
  2186. //+----------------------------------------------------------------------------
  2187. DWORD CWlbsControl::WlbsSuspend
  2188. (
  2189. DWORD cluster,
  2190. DWORD host,
  2191. PWLBS_RESPONSE response,
  2192. PDWORD num_hosts
  2193. )
  2194. {
  2195. TRACE_VERB("->%!FUNC! cluster 0x%lx, host 0x%lx", cluster, host);
  2196. LONG ioctl = IOCTL_CVY_CLUSTER_SUSPEND;
  2197. DWORD status;
  2198. IOCTL_CVY_BUF in_buf;
  2199. DWORD dwInitResult = GetInitResult();
  2200. if (dwInitResult == WLBS_INIT_ERROR)
  2201. {
  2202. TRACE_CRIT("%!FUNC! GetInitResult failed with %d", dwInitResult);
  2203. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2204. return dwInitResult;
  2205. }
  2206. if (num_hosts == NULL || *num_hosts == 0)
  2207. {
  2208. TRACE_INFO("%!FUNC! caller does not want host information returned");
  2209. response = NULL;
  2210. }
  2211. CWlbsCluster* pCluster= GetClusterFromIpOrIndex(cluster);
  2212. if (pCluster && dwInitResult == WLBS_REMOTE_ONLY)
  2213. {
  2214. TRACE_CRIT("%!FUNC! host is configured for remote action only and can't perform this action locally");
  2215. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2216. return dwInitResult;
  2217. }
  2218. if (pCluster && IsLocalHost(pCluster, host))
  2219. {
  2220. TRACE_INFO("%!FUNC! executing locally");
  2221. IOCTL_CVY_BUF out_buf;
  2222. status = WlbsLocalControl (m_hdl, pCluster->GetAdapterGuid(),
  2223. ioctl, & in_buf, & out_buf, NULL);
  2224. if (status == WLBS_IO_ERROR)
  2225. {
  2226. TRACE_CRIT("%!FUNC! local control failed with %d", status);
  2227. TRACE_VERB("<-%!FUNC! return %d", status);
  2228. return status;
  2229. }
  2230. if (num_hosts != NULL)
  2231. * num_hosts = 0;
  2232. status = MapStateFromDriverToApi (out_buf . ret_code);
  2233. }
  2234. else
  2235. {
  2236. TRACE_INFO("%!FUNC! executing remotely");
  2237. IOCTL_CVY_BUF out_buf [WLBS_MAX_HOSTS];
  2238. DWORD hosts;
  2239. DWORD i;
  2240. if (dwInitResult == WLBS_LOCAL_ONLY)
  2241. {
  2242. TRACE_CRIT("%!FUNC! host is configured for local action only and can't perform this action remotely");
  2243. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2244. return dwInitResult;
  2245. }
  2246. if (num_hosts != NULL)
  2247. hosts = * num_hosts;
  2248. else
  2249. hosts = 0;
  2250. status = WlbsRemoteControl (ioctl, & in_buf, out_buf, response, & hosts,
  2251. cluster, host, NULL, NULL /* no callback */);
  2252. if (status >= WSABASEERR || status == WLBS_TIMEOUT)
  2253. {
  2254. TRACE_CRIT("%!FUNC! remote call failed with %d", status);
  2255. TRACE_VERB("<-%!FUNC! return %d", status);
  2256. return status;
  2257. }
  2258. if (host == WLBS_ALL_HOSTS)
  2259. {
  2260. for (status = WLBS_OK, i = 0; i < hosts; i ++)
  2261. {
  2262. switch (MapStateFromDriverToApi (out_buf [i] . ret_code))
  2263. {
  2264. case WLBS_BAD_PASSW:
  2265. status = WLBS_BAD_PASSW;
  2266. break;
  2267. case WLBS_OK:
  2268. case WLBS_ALREADY:
  2269. case WLBS_STOPPED:
  2270. case WLBS_DRAIN_STOP:
  2271. default:
  2272. break;
  2273. }
  2274. }
  2275. TRACE_INFO("%!FUNC! result on all hosts is %d", status);
  2276. }
  2277. else
  2278. {
  2279. status = MapStateFromDriverToApi (out_buf [0] . ret_code);
  2280. TRACE_INFO("%!FUNC! result on host is %d", status);
  2281. }
  2282. if (num_hosts != NULL)
  2283. * num_hosts = hosts;
  2284. }
  2285. TRACE_VERB("<-%!FUNC! return %d", status);
  2286. return status;
  2287. }
  2288. //+----------------------------------------------------------------------------
  2289. //
  2290. // Function: CWlbsControl::WlbsResume
  2291. //
  2292. // Description:
  2293. //
  2294. // Arguments: WORD cluster -
  2295. // DWORD host -
  2296. // PWLBS_RESPONSE response -
  2297. // PDWORD num_hosts
  2298. //
  2299. // Returns: DWORD -
  2300. //
  2301. // History: fengsun Created Header 1/25/00
  2302. //
  2303. //+----------------------------------------------------------------------------
  2304. DWORD CWlbsControl::WlbsResume
  2305. (
  2306. DWORD cluster,
  2307. DWORD host,
  2308. PWLBS_RESPONSE response,
  2309. PDWORD num_hosts
  2310. )
  2311. {
  2312. TRACE_VERB("->%!FUNC! cluster 0x%lx, host 0x%lx", cluster, host);
  2313. LONG ioctl = IOCTL_CVY_CLUSTER_RESUME;
  2314. DWORD status;
  2315. IOCTL_CVY_BUF in_buf;
  2316. DWORD dwInitResult = GetInitResult();
  2317. if (dwInitResult == WLBS_INIT_ERROR)
  2318. {
  2319. TRACE_CRIT("%!FUNC! GetInitResult failed with %d", dwInitResult);
  2320. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2321. return dwInitResult;
  2322. }
  2323. if (num_hosts == NULL || *num_hosts == 0)
  2324. {
  2325. TRACE_INFO("%!FUNC! caller does not want host information returned");
  2326. response = NULL;
  2327. }
  2328. CWlbsCluster* pCluster = GetClusterFromIpOrIndex(cluster);
  2329. if (pCluster && dwInitResult == WLBS_REMOTE_ONLY)
  2330. {
  2331. TRACE_CRIT("%!FUNC! host is configured for remote action only and can't perform this action locally");
  2332. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2333. return dwInitResult;
  2334. }
  2335. if (pCluster && IsLocalHost(pCluster, host))
  2336. {
  2337. TRACE_INFO("%!FUNC! executing locally");
  2338. IOCTL_CVY_BUF out_buf;
  2339. status = WlbsLocalControl (m_hdl, pCluster->GetAdapterGuid(),
  2340. ioctl, & in_buf, & out_buf, NULL);
  2341. if (status == WLBS_IO_ERROR)
  2342. {
  2343. TRACE_CRIT("%!FUNC! local control failed with %d", status);
  2344. TRACE_VERB("<-%!FUNC! return %d", status);
  2345. return status;
  2346. }
  2347. if (num_hosts != NULL)
  2348. * num_hosts = 0;
  2349. status = MapStateFromDriverToApi (out_buf . ret_code);
  2350. }
  2351. else
  2352. {
  2353. TRACE_INFO("%!FUNC! executing remotely");
  2354. IOCTL_CVY_BUF out_buf [WLBS_MAX_HOSTS];
  2355. DWORD hosts;
  2356. DWORD i;
  2357. if (dwInitResult == WLBS_LOCAL_ONLY)
  2358. {
  2359. TRACE_CRIT("%!FUNC! host is configured for local action only and can't perform this action remotely");
  2360. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2361. return dwInitResult;
  2362. }
  2363. if (num_hosts != NULL)
  2364. hosts = * num_hosts;
  2365. else
  2366. hosts = 0;
  2367. status = WlbsRemoteControl (ioctl, & in_buf, out_buf, response, & hosts,
  2368. cluster, host, NULL, NULL /* no callback */);
  2369. if (status >= WSABASEERR || status == WLBS_TIMEOUT)
  2370. {
  2371. TRACE_CRIT("%!FUNC! remote call failed with %d", status);
  2372. TRACE_VERB("<-%!FUNC! return %d", status);
  2373. return status;
  2374. }
  2375. if (host == WLBS_ALL_HOSTS)
  2376. {
  2377. for (status = WLBS_OK, i = 0; i < hosts; i ++)
  2378. {
  2379. switch (MapStateFromDriverToApi (out_buf [i] . ret_code))
  2380. {
  2381. case WLBS_BAD_PASSW:
  2382. status = WLBS_BAD_PASSW;
  2383. break;
  2384. case WLBS_OK:
  2385. case WLBS_ALREADY:
  2386. default:
  2387. break;
  2388. }
  2389. }
  2390. TRACE_INFO("%!FUNC! result on all hosts is %d", status);
  2391. }
  2392. else
  2393. {
  2394. status = MapStateFromDriverToApi (out_buf [0] . ret_code);
  2395. TRACE_INFO("%!FUNC! result on host is %d", status);
  2396. }
  2397. if (num_hosts != NULL)
  2398. * num_hosts = hosts;
  2399. }
  2400. TRACE_VERB("<-%!FUNC! return %d", status);
  2401. return status;
  2402. }
  2403. //+----------------------------------------------------------------------------
  2404. //
  2405. // Function: CWlbsControl::WlbsStart
  2406. //
  2407. // Description:
  2408. //
  2409. // Arguments: WORD cluster -
  2410. // DWORD host -
  2411. // PWLBS_RESPONSE response -
  2412. // PDWORD num_hosts
  2413. //
  2414. // Returns: DWORD -
  2415. //
  2416. // History: fengsun Created Header 1/25/00
  2417. //
  2418. //+----------------------------------------------------------------------------
  2419. DWORD CWlbsControl::WlbsStart
  2420. (
  2421. DWORD cluster,
  2422. DWORD host,
  2423. PWLBS_RESPONSE response,
  2424. PDWORD num_hosts
  2425. )
  2426. {
  2427. TRACE_VERB("->%!FUNC! cluster 0x%lx, host 0x%lx", cluster, host);
  2428. LONG ioctl = IOCTL_CVY_CLUSTER_ON;
  2429. DWORD status;
  2430. IOCTL_CVY_BUF in_buf;
  2431. DWORD dwInitResult = GetInitResult();
  2432. if (dwInitResult == WLBS_INIT_ERROR)
  2433. {
  2434. TRACE_CRIT("%!FUNC! GetInitResult failed with %d", dwInitResult);
  2435. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2436. return dwInitResult;
  2437. }
  2438. if (num_hosts == NULL || *num_hosts == 0)
  2439. {
  2440. TRACE_INFO("%!FUNC! caller does not want host information returned");
  2441. response = NULL;
  2442. }
  2443. CWlbsCluster* pCluster = GetClusterFromIpOrIndex(cluster);
  2444. if (pCluster && dwInitResult == WLBS_REMOTE_ONLY)
  2445. {
  2446. TRACE_CRIT("%!FUNC! host is configured for remote action only and can't perform this action locally");
  2447. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2448. return dwInitResult;
  2449. }
  2450. if (pCluster && IsLocalHost(pCluster, host))
  2451. {
  2452. TRACE_INFO("%!FUNC! executing locally");
  2453. IOCTL_CVY_BUF out_buf;
  2454. status = WlbsLocalControl (m_hdl, pCluster->GetAdapterGuid(),
  2455. ioctl, & in_buf, & out_buf, NULL);
  2456. if (status == WLBS_IO_ERROR)
  2457. {
  2458. TRACE_CRIT("%!FUNC! local control failed with %d", status);
  2459. TRACE_VERB("<-%!FUNC! return %d", status);
  2460. return status;
  2461. }
  2462. if (num_hosts != NULL)
  2463. * num_hosts = 0;
  2464. status = MapStateFromDriverToApi (out_buf . ret_code);
  2465. }
  2466. else
  2467. {
  2468. TRACE_INFO("%!FUNC! executing remotely");
  2469. IOCTL_CVY_BUF out_buf [WLBS_MAX_HOSTS];
  2470. DWORD hosts;
  2471. DWORD i;
  2472. if (dwInitResult == WLBS_LOCAL_ONLY)
  2473. {
  2474. TRACE_CRIT("%!FUNC! host is configured for local action only and can't perform this action remotely");
  2475. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2476. return dwInitResult;
  2477. }
  2478. if (num_hosts != NULL)
  2479. hosts = * num_hosts;
  2480. else
  2481. hosts = 0;
  2482. status = WlbsRemoteControl (ioctl, & in_buf, out_buf, response, & hosts,
  2483. cluster, host, NULL, NULL /* no callback */);
  2484. if (status >= WSABASEERR || status == WLBS_TIMEOUT)
  2485. {
  2486. TRACE_CRIT("%!FUNC! remote call failed with %d", status);
  2487. TRACE_VERB("<-%!FUNC! return %d", status);
  2488. return status;
  2489. }
  2490. if (host == WLBS_ALL_HOSTS)
  2491. {
  2492. for (status = WLBS_OK, i = 0; i < hosts; i ++)
  2493. {
  2494. switch (MapStateFromDriverToApi (out_buf [i] . ret_code))
  2495. {
  2496. case WLBS_BAD_PARAMS:
  2497. if (status != WLBS_BAD_PASSW)
  2498. status = WLBS_BAD_PARAMS;
  2499. break;
  2500. case WLBS_BAD_PASSW:
  2501. status = WLBS_BAD_PASSW;
  2502. break;
  2503. case WLBS_SUSPENDED:
  2504. if (status != WLBS_BAD_PASSW && status != WLBS_BAD_PARAMS)
  2505. status = WLBS_SUSPENDED;
  2506. break;
  2507. case WLBS_OK:
  2508. case WLBS_ALREADY:
  2509. case WLBS_DRAIN_STOP:
  2510. break;
  2511. default:
  2512. break;
  2513. }
  2514. }
  2515. TRACE_INFO("%!FUNC! result on all hosts is %d", status);
  2516. }
  2517. else
  2518. {
  2519. status = MapStateFromDriverToApi (out_buf [0] . ret_code);
  2520. TRACE_INFO("%!FUNC! result on host is %d", status);
  2521. }
  2522. if (num_hosts != NULL)
  2523. * num_hosts = hosts;
  2524. }
  2525. TRACE_VERB("<-%!FUNC! return %d", status);
  2526. return status;
  2527. }
  2528. //+----------------------------------------------------------------------------
  2529. //
  2530. // Function: CWlbsControl::WlbsStop
  2531. //
  2532. // Description:
  2533. //
  2534. // Arguments: WORD cluster -
  2535. // DWORD host -
  2536. // PWLBS_RESPONSE response -
  2537. // PDWORD num_hosts
  2538. //
  2539. // Returns: DWORD -
  2540. //
  2541. // History: fengsun Created Header 1/25/00
  2542. //
  2543. //+----------------------------------------------------------------------------
  2544. DWORD CWlbsControl::WlbsStop
  2545. (
  2546. DWORD cluster,
  2547. DWORD host,
  2548. PWLBS_RESPONSE response,
  2549. PDWORD num_hosts
  2550. )
  2551. {
  2552. TRACE_VERB("->%!FUNC! cluster 0x%lx, host 0x%lx", cluster, host);
  2553. LONG ioctl = IOCTL_CVY_CLUSTER_OFF;
  2554. DWORD status;
  2555. IOCTL_CVY_BUF in_buf;
  2556. DWORD dwInitResult = GetInitResult();
  2557. if (dwInitResult == WLBS_INIT_ERROR)
  2558. {
  2559. TRACE_CRIT("%!FUNC! GetInitResult failed with %d", dwInitResult);
  2560. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2561. return dwInitResult;
  2562. }
  2563. if (num_hosts == NULL || *num_hosts == 0)
  2564. {
  2565. TRACE_INFO("%!FUNC! caller does not want host information returned");
  2566. response = NULL;
  2567. }
  2568. CWlbsCluster* pCluster = GetClusterFromIpOrIndex(cluster);
  2569. if (pCluster && dwInitResult == WLBS_REMOTE_ONLY)
  2570. {
  2571. TRACE_CRIT("%!FUNC! host is configured for remote action only and can't perform this action locally");
  2572. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2573. return dwInitResult;
  2574. }
  2575. if (pCluster && IsLocalHost(pCluster, host))
  2576. {
  2577. TRACE_INFO("%!FUNC! executing locally");
  2578. IOCTL_CVY_BUF out_buf;
  2579. status = WlbsLocalControl (m_hdl, pCluster->GetAdapterGuid(),
  2580. ioctl, & in_buf, & out_buf, NULL);
  2581. if (status == WLBS_IO_ERROR)
  2582. {
  2583. TRACE_CRIT("%!FUNC! local control failed with %d", status);
  2584. TRACE_VERB("<-%!FUNC! return %d", status);
  2585. return status;
  2586. }
  2587. if (num_hosts != NULL)
  2588. * num_hosts = 0;
  2589. status = MapStateFromDriverToApi (out_buf . ret_code);
  2590. }
  2591. else
  2592. {
  2593. TRACE_INFO("%!FUNC! executing remotely");
  2594. IOCTL_CVY_BUF out_buf [WLBS_MAX_HOSTS];
  2595. DWORD hosts;
  2596. DWORD i;
  2597. if (dwInitResult == WLBS_LOCAL_ONLY)
  2598. {
  2599. TRACE_CRIT("%!FUNC! host is configured for local action only and can't perform this action remotely");
  2600. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2601. return dwInitResult;
  2602. }
  2603. if (num_hosts != NULL)
  2604. hosts = * num_hosts;
  2605. else
  2606. hosts = 0;
  2607. status = WlbsRemoteControl (ioctl, & in_buf, out_buf, response, & hosts,
  2608. cluster, host, NULL, NULL /* no callback */);
  2609. if (status >= WSABASEERR || status == WLBS_TIMEOUT)
  2610. {
  2611. TRACE_CRIT("%!FUNC! remote call failed with %d", status);
  2612. TRACE_VERB("<-%!FUNC! return %d", status);
  2613. return status;
  2614. }
  2615. if (host == WLBS_ALL_HOSTS)
  2616. {
  2617. for (status = WLBS_OK, i = 0; i < hosts; i ++)
  2618. {
  2619. switch (MapStateFromDriverToApi (out_buf [i] . ret_code))
  2620. {
  2621. case WLBS_BAD_PASSW:
  2622. status = WLBS_BAD_PASSW;
  2623. break;
  2624. case WLBS_SUSPENDED:
  2625. if (status != WLBS_BAD_PASSW)
  2626. status = WLBS_SUSPENDED;
  2627. break;
  2628. case WLBS_OK:
  2629. case WLBS_ALREADY:
  2630. case WLBS_DRAIN_STOP:
  2631. default:
  2632. break;
  2633. }
  2634. }
  2635. TRACE_INFO("%!FUNC! result on all hosts is %d", status);
  2636. }
  2637. else
  2638. {
  2639. status = MapStateFromDriverToApi (out_buf [0] . ret_code);
  2640. TRACE_INFO("%!FUNC! result on host is %d", status);
  2641. }
  2642. if (num_hosts != NULL)
  2643. * num_hosts = hosts;
  2644. }
  2645. TRACE_VERB("<-%!FUNC! return %d", status);
  2646. return status;
  2647. }
  2648. //+----------------------------------------------------------------------------
  2649. //
  2650. // Function: CWlbsControl::WlbsDrainStop
  2651. //
  2652. // Description:
  2653. //
  2654. // Arguments: WORD cluster -
  2655. // DWORD host -
  2656. // PWLBS_RESPONSE response -
  2657. // PDWORD num_hosts
  2658. //
  2659. // Returns: DWORD -
  2660. //
  2661. // History: fengsun Created Header 1/25/00
  2662. //
  2663. //+----------------------------------------------------------------------------
  2664. DWORD CWlbsControl::WlbsDrainStop
  2665. (
  2666. DWORD cluster,
  2667. DWORD host,
  2668. PWLBS_RESPONSE response,
  2669. PDWORD num_hosts
  2670. )
  2671. {
  2672. TRACE_VERB("->%!FUNC! cluster 0x%lx, host 0x%lx", cluster, host);
  2673. LONG ioctl = IOCTL_CVY_CLUSTER_DRAIN;
  2674. DWORD status;
  2675. IOCTL_CVY_BUF in_buf;
  2676. DWORD dwInitResult = GetInitResult();
  2677. if (dwInitResult == WLBS_INIT_ERROR)
  2678. {
  2679. TRACE_CRIT("%!FUNC! GetInitResult failed with %d", dwInitResult);
  2680. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2681. return dwInitResult;
  2682. }
  2683. if (num_hosts == NULL || *num_hosts == 0)
  2684. {
  2685. TRACE_INFO("%!FUNC! caller does not want host information returned");
  2686. response = NULL;
  2687. }
  2688. CWlbsCluster* pCluster = GetClusterFromIpOrIndex(cluster);
  2689. if (pCluster && dwInitResult == WLBS_REMOTE_ONLY)
  2690. {
  2691. TRACE_CRIT("%!FUNC! host is configured for remote action only and can't perform this action locally");
  2692. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2693. return dwInitResult;
  2694. }
  2695. if (pCluster && IsLocalHost(pCluster, host))
  2696. {
  2697. TRACE_INFO("%!FUNC! executing locally");
  2698. IOCTL_CVY_BUF out_buf;
  2699. status = WlbsLocalControl (m_hdl,pCluster->GetAdapterGuid(),
  2700. ioctl, & in_buf, & out_buf, NULL);
  2701. if (status == WLBS_IO_ERROR)
  2702. {
  2703. TRACE_CRIT("%!FUNC! local control failed with %d", status);
  2704. TRACE_VERB("<-%!FUNC! return %d", status);
  2705. return status;
  2706. }
  2707. if (num_hosts != NULL)
  2708. * num_hosts = 0;
  2709. status = MapStateFromDriverToApi (out_buf . ret_code);
  2710. }
  2711. else
  2712. {
  2713. TRACE_INFO("%!FUNC! executing remotely");
  2714. IOCTL_CVY_BUF out_buf [WLBS_MAX_HOSTS];
  2715. DWORD hosts;
  2716. DWORD i;
  2717. if (dwInitResult == WLBS_LOCAL_ONLY)
  2718. {
  2719. TRACE_CRIT("%!FUNC! host is configured for local action only and can't perform this action remotely");
  2720. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2721. return dwInitResult;
  2722. }
  2723. if (num_hosts != NULL)
  2724. hosts = * num_hosts;
  2725. else
  2726. hosts = 0;
  2727. status = WlbsRemoteControl (ioctl, & in_buf, out_buf, response, & hosts,
  2728. cluster, host, NULL, NULL /* no callback */);
  2729. if (status >= WSABASEERR)
  2730. {
  2731. TRACE_CRIT("%!FUNC! remote call failed with %d", status);
  2732. TRACE_VERB("<-%!FUNC! return %d", status);
  2733. return status;
  2734. }
  2735. if (status == WLBS_TIMEOUT)
  2736. {
  2737. TRACE_INFO("%!FUNC! remote call timed out");
  2738. TRACE_VERB("<-%!FUNC! return %d", status);
  2739. return status;
  2740. }
  2741. if (host == WLBS_ALL_HOSTS)
  2742. {
  2743. for (status = WLBS_STOPPED, i = 0; i < hosts; i ++)
  2744. {
  2745. switch (MapStateFromDriverToApi (out_buf [i] . ret_code))
  2746. {
  2747. case WLBS_BAD_PASSW:
  2748. status = WLBS_BAD_PASSW;
  2749. break;
  2750. case WLBS_SUSPENDED:
  2751. if (status != WLBS_BAD_PASSW)
  2752. status = WLBS_SUSPENDED;
  2753. break;
  2754. case WLBS_OK:
  2755. case WLBS_ALREADY:
  2756. if (status != WLBS_BAD_PASSW && status != WLBS_SUSPENDED)
  2757. status = WLBS_OK;
  2758. case WLBS_STOPPED:
  2759. default:
  2760. break;
  2761. }
  2762. }
  2763. TRACE_INFO("%!FUNC! result on all hosts is %d", status);
  2764. }
  2765. else
  2766. {
  2767. status = MapStateFromDriverToApi (out_buf [0] . ret_code);
  2768. TRACE_INFO("%!FUNC! result on host is %d", status);
  2769. }
  2770. if (num_hosts != NULL)
  2771. * num_hosts = hosts;
  2772. }
  2773. TRACE_VERB("<-%!FUNC! return %d", status);
  2774. return status;
  2775. }
  2776. //+----------------------------------------------------------------------------
  2777. //
  2778. // Function: CWlbsControl::WlbsEnable
  2779. //
  2780. // Description:
  2781. //
  2782. // Arguments: WORD cluster -
  2783. // DWORD host -
  2784. // PWLBS_RESPONSE response -
  2785. // PDWORD num_hosts -
  2786. // DWORD port
  2787. //
  2788. // Returns: DWORD -
  2789. //
  2790. // History: fengsun Created Header 1/25/00
  2791. //
  2792. //+----------------------------------------------------------------------------
  2793. DWORD CWlbsControl::WlbsEnable
  2794. (
  2795. DWORD cluster,
  2796. DWORD host,
  2797. PWLBS_RESPONSE response,
  2798. PDWORD num_hosts,
  2799. DWORD vip,
  2800. DWORD port
  2801. )
  2802. {
  2803. TRACE_VERB("->%!FUNC! cluster 0x%lx, host 0x%lx", cluster, host);
  2804. LONG ioctl = IOCTL_CVY_PORT_ON;
  2805. DWORD status;
  2806. IOCTL_CVY_BUF in_buf;
  2807. DWORD dwInitResult = GetInitResult();
  2808. if (dwInitResult == WLBS_INIT_ERROR)
  2809. {
  2810. TRACE_CRIT("%!FUNC! GetInitResult failed with %d", dwInitResult);
  2811. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2812. return dwInitResult;
  2813. }
  2814. if (num_hosts == NULL || *num_hosts == 0)
  2815. {
  2816. TRACE_INFO("%!FUNC! caller does not want host information returned");
  2817. response = NULL;
  2818. }
  2819. in_buf . data . port . num = port;
  2820. CWlbsCluster* pCluster = GetClusterFromIpOrIndex(cluster);
  2821. if (pCluster && dwInitResult == WLBS_REMOTE_ONLY)
  2822. {
  2823. TRACE_CRIT("%!FUNC! host is configured for remote action only and can't perform this action locally");
  2824. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2825. return dwInitResult;
  2826. }
  2827. if (pCluster && IsLocalHost(pCluster, host))
  2828. {
  2829. TRACE_INFO("%!FUNC! executing locally");
  2830. IOCTL_CVY_BUF out_buf;
  2831. IOCTL_LOCAL_OPTIONS options;
  2832. /* Set the port options. */
  2833. options.common.port.flags = 0;
  2834. options.common.port.vip = vip;
  2835. status = WlbsLocalControl (m_hdl, pCluster->GetAdapterGuid(),
  2836. ioctl, & in_buf, & out_buf, &options);
  2837. if (status == WLBS_IO_ERROR)
  2838. {
  2839. TRACE_CRIT("%!FUNC! local control failed with %d", status);
  2840. TRACE_VERB("<-%!FUNC! return %d", status);
  2841. return status;
  2842. }
  2843. if (num_hosts != NULL)
  2844. * num_hosts = 0;
  2845. status = MapStateFromDriverToApi (out_buf . ret_code);
  2846. }
  2847. else
  2848. {
  2849. TRACE_INFO("%!FUNC! executing remotely");
  2850. IOCTL_CVY_BUF out_buf [WLBS_MAX_HOSTS];
  2851. DWORD hosts;
  2852. DWORD i;
  2853. IOCTL_REMOTE_OPTIONS options;
  2854. /* Set the port options. */
  2855. options.common.port.flags = 0;
  2856. options.common.port.vip = vip;
  2857. dwInitResult = GetInitResult();
  2858. if (dwInitResult == WLBS_LOCAL_ONLY)
  2859. {
  2860. TRACE_CRIT("%!FUNC! host is configured for local action only and can't perform this action remotely");
  2861. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2862. return dwInitResult;
  2863. }
  2864. if (num_hosts != NULL)
  2865. hosts = * num_hosts;
  2866. else
  2867. hosts = 0;
  2868. status = WlbsRemoteControl (ioctl, & in_buf, out_buf, response, & hosts,
  2869. cluster, host, &options, NULL /* no callback */);
  2870. if (status >= WSABASEERR || status == WLBS_TIMEOUT)
  2871. {
  2872. TRACE_CRIT("%!FUNC! remote call failed with %d", status);
  2873. TRACE_VERB("<-%!FUNC! return %d", status);
  2874. return status;
  2875. }
  2876. if (host == WLBS_ALL_HOSTS)
  2877. {
  2878. for (status = WLBS_OK, i = 0; i < hosts; i ++)
  2879. {
  2880. switch (MapStateFromDriverToApi (out_buf [i] . ret_code))
  2881. {
  2882. case WLBS_BAD_PASSW:
  2883. status = WLBS_BAD_PASSW;
  2884. break;
  2885. case WLBS_NOT_FOUND:
  2886. if (status != WLBS_BAD_PASSW)
  2887. status = WLBS_NOT_FOUND;
  2888. break;
  2889. case WLBS_SUSPENDED:
  2890. if (status != WLBS_BAD_PASSW && status != WLBS_NOT_FOUND)
  2891. status = WLBS_SUSPENDED;
  2892. break;
  2893. case WLBS_OK:
  2894. case WLBS_ALREADY:
  2895. case WLBS_STOPPED:
  2896. case WLBS_DRAINING:
  2897. default:
  2898. break;
  2899. }
  2900. }
  2901. TRACE_INFO("%!FUNC! result on all hosts is %d", status);
  2902. }
  2903. else
  2904. {
  2905. status = MapStateFromDriverToApi (out_buf [0] . ret_code);
  2906. TRACE_INFO("%!FUNC! result on host is %d", status);
  2907. }
  2908. if (num_hosts != NULL)
  2909. * num_hosts = hosts;
  2910. }
  2911. TRACE_VERB("<-%!FUNC! return %d", status);
  2912. return status;
  2913. }
  2914. //+----------------------------------------------------------------------------
  2915. //
  2916. // Function: CWlbsControl::WlbsDisable
  2917. //
  2918. // Description:
  2919. //
  2920. // Arguments: WORD cluster -
  2921. // DWORD host -
  2922. // PWLBS_RESPONSE response -
  2923. // PDWORD num_hosts -
  2924. // DWORD port
  2925. //
  2926. // Returns: DWORD -
  2927. //
  2928. // History: fengsun Created Header 1/25/00
  2929. //
  2930. //+----------------------------------------------------------------------------
  2931. DWORD CWlbsControl::WlbsDisable
  2932. (
  2933. DWORD cluster,
  2934. DWORD host,
  2935. PWLBS_RESPONSE response,
  2936. PDWORD num_hosts,
  2937. DWORD vip,
  2938. DWORD port
  2939. )
  2940. {
  2941. TRACE_VERB("->%!FUNC! cluster 0x%lx, host 0x%lx", cluster, host);
  2942. LONG ioctl = IOCTL_CVY_PORT_OFF;
  2943. DWORD status;
  2944. IOCTL_CVY_BUF in_buf;
  2945. DWORD dwInitResult = GetInitResult();
  2946. if (dwInitResult == WLBS_INIT_ERROR)
  2947. {
  2948. TRACE_CRIT("%!FUNC! GetInitResult failed with %d", dwInitResult);
  2949. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2950. return dwInitResult;
  2951. }
  2952. if (num_hosts == NULL || *num_hosts == 0)
  2953. {
  2954. TRACE_INFO("%!FUNC! caller does not want host information returned");
  2955. response = NULL;
  2956. }
  2957. in_buf . data . port . num = port;
  2958. CWlbsCluster* pCluster = GetClusterFromIpOrIndex(cluster);
  2959. dwInitResult = GetInitResult();
  2960. if (pCluster && (dwInitResult == WLBS_REMOTE_ONLY))
  2961. {
  2962. TRACE_CRIT("%!FUNC! host is configured for remote action only and can't perform this action locally");
  2963. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  2964. return dwInitResult;
  2965. }
  2966. if (pCluster && IsLocalHost(pCluster, host))
  2967. {
  2968. TRACE_INFO("%!FUNC! executing locally");
  2969. IOCTL_CVY_BUF out_buf;
  2970. IOCTL_LOCAL_OPTIONS options;
  2971. /* Set the port options. */
  2972. options.common.port.flags = 0;
  2973. options.common.port.vip = vip;
  2974. status = WlbsLocalControl (m_hdl, pCluster->GetAdapterGuid(),
  2975. ioctl, & in_buf, & out_buf, &options);
  2976. if (status == WLBS_IO_ERROR)
  2977. {
  2978. TRACE_CRIT("%!FUNC! local control failed with %d", status);
  2979. TRACE_VERB("<-%!FUNC! return %d", status);
  2980. return status;
  2981. }
  2982. if (num_hosts != NULL)
  2983. * num_hosts = 0;
  2984. status = MapStateFromDriverToApi (out_buf . ret_code);
  2985. }
  2986. else
  2987. {
  2988. TRACE_INFO("%!FUNC! executing remotely");
  2989. IOCTL_CVY_BUF out_buf [WLBS_MAX_HOSTS];
  2990. DWORD hosts;
  2991. DWORD i;
  2992. IOCTL_REMOTE_OPTIONS options;
  2993. /* Set the port options. */
  2994. options.common.port.flags = 0;
  2995. options.common.port.vip = vip;
  2996. if (dwInitResult == WLBS_LOCAL_ONLY)
  2997. {
  2998. TRACE_CRIT("%!FUNC! host is configured for local action only and can't perform this action remotely");
  2999. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  3000. return dwInitResult;
  3001. }
  3002. if (num_hosts != NULL)
  3003. hosts = * num_hosts;
  3004. else
  3005. hosts = 0;
  3006. status = WlbsRemoteControl (ioctl, & in_buf, out_buf, response, & hosts,
  3007. cluster, host, &options, NULL /* no callback */);
  3008. if (status >= WSABASEERR || status == WLBS_TIMEOUT)
  3009. {
  3010. TRACE_CRIT("%!FUNC! remote call failed with %d", status);
  3011. TRACE_VERB("<-%!FUNC! return %d", status);
  3012. return status;
  3013. }
  3014. if (host == WLBS_ALL_HOSTS)
  3015. {
  3016. for (status = WLBS_OK, i = 0; i < hosts; i ++)
  3017. {
  3018. switch (MapStateFromDriverToApi (out_buf [i] . ret_code))
  3019. {
  3020. case WLBS_BAD_PASSW:
  3021. status = WLBS_BAD_PASSW;
  3022. break;
  3023. case WLBS_NOT_FOUND:
  3024. if (status != WLBS_BAD_PASSW)
  3025. status = WLBS_NOT_FOUND;
  3026. break;
  3027. case WLBS_SUSPENDED:
  3028. if (status != WLBS_BAD_PASSW && status != WLBS_NOT_FOUND)
  3029. status = WLBS_SUSPENDED;
  3030. break;
  3031. case WLBS_OK:
  3032. case WLBS_ALREADY:
  3033. case WLBS_STOPPED:
  3034. case WLBS_DRAINING:
  3035. default:
  3036. break;
  3037. }
  3038. }
  3039. TRACE_INFO("%!FUNC! result on all hosts is %d", status);
  3040. }
  3041. else
  3042. {
  3043. status = MapStateFromDriverToApi (out_buf [0] . ret_code);
  3044. TRACE_INFO("%!FUNC! result on host is %d", status);
  3045. }
  3046. if (num_hosts != NULL)
  3047. * num_hosts = hosts;
  3048. }
  3049. TRACE_VERB("<-%!FUNC! return %d", status);
  3050. return status;
  3051. }
  3052. //+----------------------------------------------------------------------------
  3053. //
  3054. // Function: CWlbsControl::WlbsDrain
  3055. //
  3056. // Description:
  3057. //
  3058. // Arguments: WORD cluster -
  3059. // DWORD host -
  3060. // PWLBS_RESPONSE response -
  3061. // PDWORD num_hosts -
  3062. // DWORD port
  3063. //
  3064. // Returns: DWORD -
  3065. //
  3066. // History: fengsun Created Header 1/25/00
  3067. //
  3068. //+----------------------------------------------------------------------------
  3069. DWORD CWlbsControl::WlbsDrain
  3070. (
  3071. DWORD cluster,
  3072. DWORD host,
  3073. PWLBS_RESPONSE response,
  3074. PDWORD num_hosts,
  3075. DWORD vip,
  3076. DWORD port
  3077. )
  3078. {
  3079. TRACE_VERB("->%!FUNC! cluster 0x%lx, host 0x%lx", cluster, host);
  3080. LONG ioctl = IOCTL_CVY_PORT_DRAIN;
  3081. DWORD status;
  3082. IOCTL_CVY_BUF in_buf;
  3083. DWORD dwInitResult = GetInitResult();
  3084. if (dwInitResult == WLBS_INIT_ERROR)
  3085. {
  3086. TRACE_CRIT("%!FUNC! GetInitResult failed with %d", dwInitResult);
  3087. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  3088. return dwInitResult;
  3089. }
  3090. if (num_hosts == NULL || *num_hosts == 0)
  3091. {
  3092. TRACE_INFO("%!FUNC! caller does not want host information returned");
  3093. response = NULL;
  3094. }
  3095. in_buf . data . port . num = port;
  3096. CWlbsCluster* pCluster = GetClusterFromIpOrIndex(cluster);
  3097. if (pCluster && dwInitResult == WLBS_REMOTE_ONLY)
  3098. {
  3099. TRACE_CRIT("%!FUNC! host is configured for remote action only and can't perform this action locally");
  3100. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  3101. return dwInitResult;
  3102. }
  3103. if (pCluster && IsLocalHost(pCluster, host))
  3104. {
  3105. TRACE_INFO("%!FUNC! executing locally");
  3106. IOCTL_CVY_BUF out_buf;
  3107. IOCTL_LOCAL_OPTIONS options;
  3108. /* Set the port options. */
  3109. options.common.port.flags = 0;
  3110. options.common.port.vip = vip;
  3111. status = WlbsLocalControl (m_hdl, pCluster->GetAdapterGuid(),
  3112. ioctl, & in_buf, & out_buf, &options);
  3113. if (status == WLBS_IO_ERROR)
  3114. {
  3115. TRACE_CRIT("%!FUNC! local control failed with %d", status);
  3116. TRACE_VERB("<-%!FUNC! return %d", status);
  3117. return status;
  3118. }
  3119. if (num_hosts != NULL)
  3120. * num_hosts = 0;
  3121. status = MapStateFromDriverToApi (out_buf . ret_code);
  3122. }
  3123. else
  3124. {
  3125. TRACE_INFO("%!FUNC! executing remotely");
  3126. IOCTL_CVY_BUF out_buf [WLBS_MAX_HOSTS];
  3127. DWORD hosts;
  3128. DWORD i;
  3129. IOCTL_REMOTE_OPTIONS options;
  3130. /* Set the port options. */
  3131. options.common.port.flags = 0;
  3132. options.common.port.vip = vip;
  3133. if (dwInitResult == WLBS_LOCAL_ONLY)
  3134. {
  3135. TRACE_CRIT("%!FUNC! host is configured for local action only and can't perform this action remotely");
  3136. TRACE_VERB("<-%!FUNC! return %d", dwInitResult);
  3137. return dwInitResult;
  3138. }
  3139. if (num_hosts != NULL)
  3140. hosts = * num_hosts;
  3141. else
  3142. hosts = 0;
  3143. status = WlbsRemoteControl (ioctl, & in_buf, out_buf, response, & hosts,
  3144. cluster, host, &options, NULL /* no callback */);
  3145. if (status >= WSABASEERR || status == WLBS_TIMEOUT)
  3146. {
  3147. TRACE_CRIT("%!FUNC! remote call failed with %d", status);
  3148. TRACE_VERB("<-%!FUNC! return %d", status);
  3149. return status;
  3150. }
  3151. if (host == WLBS_ALL_HOSTS)
  3152. {
  3153. for (status = WLBS_OK, i = 0; i < hosts; i ++)
  3154. {
  3155. switch (MapStateFromDriverToApi (out_buf [i] . ret_code))
  3156. {
  3157. case WLBS_BAD_PASSW:
  3158. status = WLBS_BAD_PASSW;
  3159. break;
  3160. case WLBS_NOT_FOUND:
  3161. if (status != WLBS_BAD_PASSW)
  3162. status = WLBS_NOT_FOUND;
  3163. break;
  3164. case WLBS_SUSPENDED:
  3165. if (status != WLBS_BAD_PASSW && status != WLBS_NOT_FOUND)
  3166. status = WLBS_SUSPENDED;
  3167. break;
  3168. case WLBS_OK:
  3169. case WLBS_ALREADY:
  3170. case WLBS_STOPPED:
  3171. case WLBS_DRAINING:
  3172. default:
  3173. break;
  3174. }
  3175. }
  3176. TRACE_INFO("%!FUNC! result on all hosts is %d", status);
  3177. }
  3178. else
  3179. {
  3180. status = MapStateFromDriverToApi (out_buf [0] . ret_code);
  3181. TRACE_INFO("%!FUNC! result on host is %d", status);
  3182. }
  3183. if (num_hosts != NULL)
  3184. * num_hosts = hosts;
  3185. }
  3186. TRACE_VERB("<-%!FUNC! return %d", status);
  3187. return status;
  3188. }
  3189. //+----------------------------------------------------------------------------
  3190. //
  3191. // Function: CWlbsControl::WlbsPortSet
  3192. //
  3193. // Description:
  3194. //
  3195. // Arguments: DWORD cluster -
  3196. // WORD port -
  3197. //
  3198. // Returns: Nothing
  3199. //
  3200. // History: fengsun Created Header 1/25/00
  3201. //
  3202. //+----------------------------------------------------------------------------
  3203. VOID CWlbsControl::WlbsPortSet(DWORD cluster, WORD port)
  3204. {
  3205. TRACE_VERB("->%!FUNC! cluster 0x%lx, port 0x%hx", cluster, port);
  3206. DWORD i;
  3207. DWORD j;
  3208. WORD rct_port;
  3209. // LOCK(global_info.lock);
  3210. if (port == 0)
  3211. rct_port = CVY_DEF_RCT_PORT;
  3212. else
  3213. rct_port = port;
  3214. TRACE_INFO("%!FUNC! using remote control port %d", rct_port);
  3215. if (cluster == WLBS_ALL_CLUSTERS)
  3216. {
  3217. TRACE_INFO("%!FUNC! performing action on all cluster instances");
  3218. /* when all clusters are targeted - change the default and go through
  3219. the entire parameter table setting new values */
  3220. m_def_port = rct_port;
  3221. for (i = 0; i < WLBS_MAX_CLUSTERS; i ++)
  3222. m_cluster_params [i] . port = rct_port;
  3223. }
  3224. else
  3225. {
  3226. TRACE_INFO("%!FUNC! performing action on cluster %d", cluster);
  3227. for (i = 0, j = WLBS_MAX_CLUSTERS; i < WLBS_MAX_CLUSTERS; i ++)
  3228. {
  3229. /* mark an empty slot in case we will have to enter a new value */
  3230. if (j == WLBS_MAX_CLUSTERS && m_cluster_params [i] . cluster == 0)
  3231. j = i;
  3232. if (m_cluster_params [i] . cluster == cluster)
  3233. {
  3234. m_cluster_params [i] . port = rct_port;
  3235. TRACE_INFO("%!FUNC! cluster %d found and port set to %d", cluster, rct_port);
  3236. break;
  3237. }
  3238. }
  3239. /* if we did not locate specified cluster in the table and there is an
  3240. empty slot - enter new cluster info in the table */
  3241. if (i >= WLBS_MAX_CLUSTERS && j != WLBS_MAX_CLUSTERS)
  3242. {
  3243. m_cluster_params [j] . cluster = cluster;
  3244. m_cluster_params [j] . port = rct_port;
  3245. TRACE_INFO("%!FUNC! cluster %d was not found. A new entry was made and the port set to %d", cluster, rct_port);
  3246. }
  3247. }
  3248. // UNLOCK(global_info.lock);
  3249. TRACE_VERB("<-%!FUNC!");
  3250. }
  3251. //+----------------------------------------------------------------------------
  3252. //
  3253. // Function: CWlbsControl::WlbsPasswordSet
  3254. //
  3255. // Description:
  3256. //
  3257. // Arguments: WORD cluster -
  3258. // PTCHAR password
  3259. //
  3260. // Returns: Nothing
  3261. //
  3262. // History: fengsun Created Header 1/25/00
  3263. //
  3264. //+----------------------------------------------------------------------------
  3265. VOID CWlbsControl::WlbsPasswordSet
  3266. (
  3267. DWORD cluster,
  3268. const WCHAR* password
  3269. )
  3270. {
  3271. TRACE_VERB("->%!FUNC! cluster 0x%lx", cluster);
  3272. DWORD i;
  3273. DWORD j;
  3274. DWORD passw;
  3275. // LOCK(global_info.lock);
  3276. if (password != NULL)
  3277. {
  3278. #ifndef UNICODE
  3279. passw = License_string_encode (password);
  3280. #else
  3281. passw = License_wstring_encode((WCHAR*)password);
  3282. #endif
  3283. TRACE_INFO("%!FUNC! using user-provided password");
  3284. }
  3285. else
  3286. {
  3287. passw = CVY_DEF_RCT_PASSWORD;
  3288. TRACE_INFO("%!FUNC! password not provided. Using default.");
  3289. }
  3290. if (cluster == WLBS_ALL_CLUSTERS)
  3291. {
  3292. TRACE_INFO("%!FUNC! performing action on all cluster instances");
  3293. /* when all clusters are targeted - change the default and go through
  3294. the entire parameter table setting new values */
  3295. m_def_passw = passw;
  3296. for (i = 0; i < WLBS_MAX_CLUSTERS; i ++)
  3297. m_cluster_params [i] . passw = passw;
  3298. }
  3299. else
  3300. {
  3301. TRACE_INFO("%!FUNC! performing action on cluster 0x%lx", cluster);
  3302. for (i = 0, j = WLBS_MAX_CLUSTERS; i < WLBS_MAX_CLUSTERS; i ++)
  3303. {
  3304. /* mark an empty slot in case we will have to enter a new value */
  3305. if (j == WLBS_MAX_CLUSTERS && m_cluster_params [i] . cluster == 0)
  3306. j = i;
  3307. if (m_cluster_params [i] . cluster == cluster)
  3308. {
  3309. m_cluster_params [i] . passw = passw;
  3310. TRACE_INFO("%!FUNC! cluster %d found and password was set", cluster);
  3311. break;
  3312. }
  3313. }
  3314. /* if we did not locate specified cluster in the table and there is an
  3315. empty slot - enter new cluster info in the table */
  3316. if (i >= WLBS_MAX_CLUSTERS && j != WLBS_MAX_CLUSTERS)
  3317. {
  3318. m_cluster_params [j] . cluster = cluster;
  3319. m_cluster_params [j] . passw = passw;
  3320. TRACE_INFO("%!FUNC! cluster 0x%lx was not found. A new entry was made and the password was set", cluster);
  3321. }
  3322. }
  3323. // UNLOCK(global_info.lock);
  3324. TRACE_VERB("<-%!FUNC!");
  3325. } /* end WlbsPasswordSet */
  3326. VOID CWlbsControl::WlbsCodeSet
  3327. (
  3328. DWORD cluster,
  3329. DWORD passw
  3330. )
  3331. {
  3332. TRACE_VERB("->%!FUNC! cluster 0x%lx", cluster);
  3333. DWORD i;
  3334. DWORD j;
  3335. // LOCK(global_info.lock);
  3336. if (cluster == WLBS_ALL_CLUSTERS)
  3337. {
  3338. TRACE_INFO("%!FUNC! performing action on all cluster instances");
  3339. /* when all clusters are targeted - change the default and go through
  3340. the entire parameter table setting new values */
  3341. m_def_passw = passw;
  3342. for (i = 0; i < WLBS_MAX_CLUSTERS; i ++)
  3343. m_cluster_params [i] . passw = passw;
  3344. }
  3345. else
  3346. {
  3347. TRACE_INFO("%!FUNC! performing action on cluster 0x%lx", cluster);
  3348. for (i = 0, j = WLBS_MAX_CLUSTERS; i < WLBS_MAX_CLUSTERS; i ++)
  3349. {
  3350. /* mark an empty slot in case we will have to enter a new value */
  3351. if (j == WLBS_MAX_CLUSTERS && m_cluster_params [i] . cluster == 0)
  3352. j = i;
  3353. if (m_cluster_params [i] . cluster == cluster)
  3354. {
  3355. m_cluster_params [i] . passw = passw;
  3356. TRACE_INFO("%!FUNC! cluster 0x%lx found and password was set", cluster);
  3357. break;
  3358. }
  3359. }
  3360. /* if we did not locate specified cluster in the table and there is an
  3361. empty slot - enter new cluster info in the table */
  3362. if (i >= WLBS_MAX_CLUSTERS && j != WLBS_MAX_CLUSTERS)
  3363. {
  3364. m_cluster_params [j] . cluster = cluster;
  3365. m_cluster_params [j] . passw = passw;
  3366. TRACE_INFO("%!FUNC! cluster 0x%lx was not found. A new entry was made and the password was set", cluster);
  3367. }
  3368. }
  3369. // UNLOCK(global_info.lock);
  3370. TRACE_VERB("<-%!FUNC!");
  3371. } /* end WlbsCodeSet */
  3372. VOID CWlbsControl::WlbsDestinationSet
  3373. (
  3374. DWORD cluster,
  3375. DWORD dest
  3376. )
  3377. {
  3378. TRACE_VERB("->%!FUNC! cluster 0x%lx, dest 0x%lx", cluster, dest);
  3379. DWORD i;
  3380. DWORD j;
  3381. // LOCK(global_info.lock);
  3382. if (cluster == WLBS_ALL_CLUSTERS)
  3383. {
  3384. TRACE_INFO("%!FUNC! performing action on all cluster instances");
  3385. /* when all clusters are targeted - change the default and go through
  3386. the entire parameter table setting new values */
  3387. m_def_dst_addr = dest;
  3388. for (i = 0; i < WLBS_MAX_CLUSTERS; i ++)
  3389. m_cluster_params [i] . dest = dest;
  3390. }
  3391. else
  3392. {
  3393. TRACE_INFO("%!FUNC! performing action on cluster 0x%lx", cluster);
  3394. for (i = 0, j = WLBS_MAX_CLUSTERS; i < WLBS_MAX_CLUSTERS; i ++)
  3395. {
  3396. /* mark an empty slot in case we will have to enter a new value */
  3397. if (j == WLBS_MAX_CLUSTERS && m_cluster_params [i] . cluster == 0)
  3398. j = i;
  3399. if (m_cluster_params [i] . cluster == cluster)
  3400. {
  3401. TRACE_INFO("%!FUNC! cluster 0x%lx found and destination set to %d", cluster, dest);
  3402. m_cluster_params [i] . dest = dest;
  3403. break;
  3404. }
  3405. }
  3406. /* if we did not locate specified cluster in the table and there is an
  3407. empty slot - enter new cluster info in the table */
  3408. if (i >= WLBS_MAX_CLUSTERS && j != WLBS_MAX_CLUSTERS)
  3409. {
  3410. m_cluster_params [j] . cluster = cluster;
  3411. m_cluster_params [j] . dest = dest;
  3412. TRACE_INFO("%!FUNC! cluster 0x%lx was not found. A new entry was made and the desintation set to 0x%lx", cluster, dest);
  3413. }
  3414. }
  3415. // UNLOCK(global_info.lock);
  3416. TRACE_VERB("<-%!FUNC!");
  3417. }
  3418. //+----------------------------------------------------------------------------
  3419. //
  3420. // Function: CWlbsControl::WlbsTimeoutSet
  3421. //
  3422. // Description:
  3423. //
  3424. // Arguments: DWORD cluster -
  3425. // DWORD milliseconds -
  3426. //
  3427. // Returns: Nothing
  3428. //
  3429. // History: fengsun Created Header 1/25/00
  3430. //
  3431. //+----------------------------------------------------------------------------
  3432. VOID CWlbsControl::WlbsTimeoutSet(DWORD cluster, DWORD milliseconds)
  3433. {
  3434. TRACE_VERB("->%!FUNC! cluster 0x%lx, milliseconds 0x%lx", cluster, milliseconds);
  3435. DWORD i;
  3436. DWORD j;
  3437. DWORD timeout;
  3438. // LOCK(global_info.lock);
  3439. if (milliseconds == 0)
  3440. timeout = IOCTL_REMOTE_RECV_DELAY;
  3441. else
  3442. timeout = milliseconds / (IOCTL_REMOTE_SEND_RETRIES *
  3443. IOCTL_REMOTE_RECV_RETRIES);
  3444. if (timeout < 10)
  3445. timeout = 10;
  3446. TRACE_INFO("%!FUNC! using timeout value of %d", timeout);
  3447. if (cluster == WLBS_ALL_CLUSTERS)
  3448. {
  3449. TRACE_INFO("%!FUNC! performing action on all cluster instances");
  3450. /* when all clusters are targeted - change the default and go through
  3451. the entire parameter table setting new values */
  3452. m_def_timeout = timeout;
  3453. for (i = 0; i < WLBS_MAX_CLUSTERS; i ++)
  3454. m_cluster_params [i] . timeout = timeout;
  3455. }
  3456. else
  3457. {
  3458. TRACE_INFO("%!FUNC! performing action on cluster 0x%lx", cluster);
  3459. for (i = 0, j = WLBS_MAX_CLUSTERS; i < WLBS_MAX_CLUSTERS; i ++)
  3460. {
  3461. /* mark an empty slot in case we will have to enter a new value */
  3462. if (j == WLBS_MAX_CLUSTERS && m_cluster_params [i] . cluster == 0)
  3463. j = i;
  3464. if (m_cluster_params [i] . cluster == cluster)
  3465. {
  3466. m_cluster_params [i] . timeout = timeout;
  3467. TRACE_INFO("%!FUNC! cluster 0x%lx found and timeout set to %d", cluster, timeout);
  3468. break;
  3469. }
  3470. }
  3471. /* if we did not locate specified cluster in the table and there is an
  3472. empty slot - enter new cluster info in the table */
  3473. if (i >= WLBS_MAX_CLUSTERS && j < WLBS_MAX_CLUSTERS)
  3474. {
  3475. m_cluster_params [j] . cluster = cluster;
  3476. m_cluster_params [j] . timeout = timeout;
  3477. TRACE_INFO("%!FUNC! cluster 0x%lx was not found. A new entry was made and the timeout to %d", cluster, timeout);
  3478. }
  3479. }
  3480. // UNLOCK(global_info.lock);
  3481. TRACE_VERB("<-%!FUNC!");
  3482. } /* end WlbsTimeoutSet */
  3483. DWORD CWlbsControl::WlbsQueryLocalState (CWlbsCluster * pCluster, DWORD operation, PNLB_OPTIONS pOptions, PWLBS_RESPONSE pResponse, PDWORD pcResponses) {
  3484. DWORD status = WLBS_OK;
  3485. IOCTL_CVY_BUF in_buf;
  3486. IOCTL_CVY_BUF out_buf;
  3487. IOCTL_LOCAL_OPTIONS localOptions;
  3488. ASSERT(pCluster);
  3489. ASSERT(pOptions);
  3490. ASSERT(pResponse);
  3491. ASSERT(pcResponses);
  3492. switch (operation) {
  3493. case IOCTL_CVY_QUERY_BDA_TEAMING:
  3494. localOptions.state.flags = 0;
  3495. localOptions.state.bda = pOptions->state.bda;
  3496. status = WlbsLocalControl(m_hdl, pCluster->GetAdapterGuid(), operation, &in_buf, &out_buf, &localOptions);
  3497. if (status == WLBS_IO_ERROR) return WLBS_IO_ERROR;
  3498. pResponse[0].id = out_buf.data.query.host_id;
  3499. pResponse[0].address = 0;
  3500. pResponse[0].status = MapStateFromDriverToApi(out_buf.ret_code);
  3501. pResponse[0].options.state.flags = localOptions.state.flags;
  3502. pResponse[0].options.state.bda = localOptions.state.bda;
  3503. if (pcResponses != NULL) *pcResponses = 1;
  3504. break;
  3505. case IOCTL_CVY_QUERY_PARAMS:
  3506. localOptions.state.flags = 0;
  3507. localOptions.state.params = pOptions->state.params;
  3508. status = WlbsLocalControl(m_hdl, pCluster->GetAdapterGuid(), operation, &in_buf, &out_buf, &localOptions);
  3509. if (status == WLBS_IO_ERROR) return WLBS_IO_ERROR;
  3510. pResponse[0].id = out_buf.data.query.host_id;
  3511. pResponse[0].address = 0;
  3512. pResponse[0].status = MapStateFromDriverToApi(out_buf.ret_code);
  3513. pResponse[0].options.state.flags = localOptions.state.flags;
  3514. pResponse[0].options.state.params = localOptions.state.params;
  3515. if (pcResponses != NULL) *pcResponses = 1;
  3516. break;
  3517. case IOCTL_CVY_QUERY_PORT_STATE:
  3518. localOptions.common.state.flags = 0;
  3519. localOptions.common.state.port = pOptions->state.port;
  3520. status = WlbsLocalControl(m_hdl, pCluster->GetAdapterGuid(), operation, &in_buf, &out_buf, &localOptions);
  3521. if (status == WLBS_IO_ERROR) return WLBS_IO_ERROR;
  3522. pResponse[0].id = out_buf.data.query.host_id;
  3523. pResponse[0].address = 0;
  3524. pResponse[0].status = MapStateFromDriverToApi(out_buf.ret_code);
  3525. pResponse[0].options.state.flags = localOptions.common.state.flags;
  3526. pResponse[0].options.state.port = localOptions.common.state.port;
  3527. if (pcResponses != NULL) *pcResponses = 1;
  3528. break;
  3529. case IOCTL_CVY_QUERY_FILTER:
  3530. localOptions.common.state.flags = 0;
  3531. localOptions.common.state.filter = pOptions->state.filter;
  3532. status = WlbsLocalControl(m_hdl, pCluster->GetAdapterGuid(), operation, &in_buf, &out_buf, &localOptions);
  3533. if (status == WLBS_IO_ERROR) return WLBS_IO_ERROR;
  3534. pResponse[0].id = out_buf.data.query.host_id;
  3535. pResponse[0].address = 0;
  3536. pResponse[0].status = MapStateFromDriverToApi(out_buf.ret_code);
  3537. pResponse[0].options.state.flags = localOptions.common.state.flags;
  3538. pResponse[0].options.state.filter = localOptions.common.state.filter;
  3539. if (pcResponses != NULL) *pcResponses = 1;
  3540. break;
  3541. default:
  3542. return WLBS_IO_ERROR;
  3543. }
  3544. return status;
  3545. }
  3546. DWORD CWlbsControl::WlbsQueryRemoteState (DWORD cluster, DWORD host, DWORD operation, PNLB_OPTIONS pOptions, PWLBS_RESPONSE pResponse, PDWORD pcResponses) {
  3547. DWORD status = WLBS_OK;
  3548. IOCTL_CVY_BUF in_buf;
  3549. IOCTL_CVY_BUF out_buf[WLBS_MAX_HOSTS];
  3550. IOCTL_REMOTE_OPTIONS remoteOptions;
  3551. BOOLEAN bIsMember = IsClusterMember(cluster);
  3552. ASSERT(pOptions);
  3553. ASSERT(pResponse);
  3554. ASSERT(pcResponses);
  3555. if (GetInitResult() == WLBS_LOCAL_ONLY) return WLBS_LOCAL_ONLY;
  3556. switch (operation) {
  3557. case IOCTL_CVY_QUERY_PARAMS:
  3558. case IOCTL_CVY_QUERY_BDA_TEAMING:
  3559. return WLBS_LOCAL_ONLY;
  3560. case IOCTL_CVY_QUERY_PORT_STATE:
  3561. remoteOptions.common.state.flags = 0;
  3562. remoteOptions.common.state.port = pOptions->state.port;
  3563. status = WlbsRemoteControl(operation, &in_buf, out_buf, pResponse, pcResponses, cluster, host, &remoteOptions, NULL /* no callback */);
  3564. if (status >= WSABASEERR || status == WLBS_TIMEOUT) *pcResponses = 0;
  3565. break;
  3566. case IOCTL_CVY_QUERY_FILTER:
  3567. remoteOptions.common.state.flags = 0;
  3568. remoteOptions.common.state.filter = pOptions->state.filter;
  3569. status = WlbsRemoteControl(operation, &in_buf, out_buf, pResponse, pcResponses, cluster, host, &remoteOptions, NULL /* no callback */);
  3570. if (status >= WSABASEERR || status == WLBS_TIMEOUT) *pcResponses = 0;
  3571. break;
  3572. default:
  3573. return WLBS_IO_ERROR;
  3574. }
  3575. return status;
  3576. }
  3577. DWORD CWlbsControl::WlbsQueryState (DWORD cluster, DWORD host, DWORD operation, PNLB_OPTIONS pOptions, PWLBS_RESPONSE pResponse, PDWORD pcResponses) {
  3578. DWORD status = WLBS_OK;
  3579. CWlbsCluster * pCluster = NULL;
  3580. ASSERT(pOptions);
  3581. ASSERT(pResponse);
  3582. ASSERT(pcResponses);
  3583. if (GetInitResult() == WLBS_INIT_ERROR) return WLBS_INIT_ERROR;
  3584. if (cluster == WLBS_LOCAL_CLUSTER && (GetInitResult() == WLBS_REMOTE_ONLY)) return WLBS_REMOTE_ONLY;
  3585. pCluster = GetClusterFromIpOrIndex(cluster);
  3586. if (!pCluster || !IsLocalHost(pCluster, host))
  3587. status = WlbsQueryRemoteState(cluster, host, operation, pOptions, pResponse, pcResponses);
  3588. else
  3589. status = WlbsQueryLocalState(pCluster, operation, pOptions, pResponse, pcResponses);
  3590. return status;
  3591. }
  3592. //+----------------------------------------------------------------------------
  3593. //
  3594. // Function: DllMain
  3595. //
  3596. // Description: Dll entry point
  3597. //
  3598. // Arguments: HINSTANCE handle -
  3599. // DWORD reason -
  3600. // LPVOID situation -
  3601. //
  3602. // Returns: BOOL WINAPI -
  3603. //
  3604. // History: fengsun Created Header 3/2/00
  3605. //
  3606. //+----------------------------------------------------------------------------
  3607. BOOL WINAPI DllMain(HINSTANCE handle, DWORD reason, LPVOID situation)
  3608. {
  3609. BOOL fRet = TRUE;
  3610. switch (reason)
  3611. {
  3612. case DLL_PROCESS_ATTACH:
  3613. _tsetlocale (LC_ALL, _TEXT(".OCP"));
  3614. DisableThreadLibraryCalls(handle);
  3615. g_hInstCtrl = handle;
  3616. //
  3617. // Enable tracing
  3618. //
  3619. WPP_INIT_TRACING(L"Microsoft\\NLB");
  3620. if (WlbsInitializeConnectionNotify() != ERROR_SUCCESS)
  3621. {
  3622. fRet = FALSE;
  3623. }
  3624. break;
  3625. case DLL_THREAD_ATTACH:
  3626. break;
  3627. case DLL_PROCESS_DETACH:
  3628. //
  3629. // Disable tracing
  3630. //
  3631. WPP_CLEANUP();
  3632. WlbsUninitializeConnectionNotify();
  3633. break;
  3634. case DLL_THREAD_DETACH:
  3635. break;
  3636. default:
  3637. fRet = FALSE;
  3638. break;
  3639. }
  3640. return fRet;
  3641. }