Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

602 lines
12 KiB

  1. /*++
  2. Copyright(c) 2001 Microsoft Corporation
  3. Module Name:
  4. NLB Manager
  5. File Name:
  6. nlbhost.cpp
  7. Abstract:
  8. Implementation of class NLBHost
  9. NLBHost is responsible for connecting to an NLB host and getting/setting
  10. its NLB-related configuration.
  11. History:
  12. 03/31/01 JosephJ Created
  13. --*/
  14. #include "stdafx.h"
  15. #include "private.h"
  16. //
  17. // Static members of class NLBHost.
  18. //
  19. WSADATA NLBHost::s_WsaData;
  20. LONG NLBHost::s_InstanceCount;
  21. BOOL NLBHost::s_FatalError;
  22. BOOL NLBHost::s_WsaInitialized;
  23. BOOL NLBHost::s_ComInitialized;
  24. IWbemStatusCodeTextPtr NLBHost::s_sp_werr; // Smart pointer
  25. VOID
  26. NLBHost::mfn_Log(
  27. UINT ID,
  28. ...
  29. )
  30. {
  31. WCHAR wszBuffer[1024];
  32. LPCWSTR pwszMessage;
  33. CString FormatString;
  34. if (!FormatString.LoadString(ID))
  35. {
  36. wsprintf(wszBuffer, L"Error loading string resource ID %d", ID);
  37. }
  38. else
  39. {
  40. try {
  41. va_list arglist;
  42. va_start (arglist, ID);
  43. int cch = vswprintf(wszBuffer, FormatString, arglist);
  44. va_end (arglist);
  45. }
  46. catch(...)
  47. {
  48. wsprintf(wszBuffer, L"Exception writing out log entry for resource ID %d", ID);
  49. }
  50. }
  51. m_pfnLogger(m_pLoggerContext, wszBuffer);
  52. }
  53. VOID
  54. NLBHost::mfn_LogHr(
  55. LPCWSTR pwszMessage,
  56. HRESULT hr
  57. )
  58. {
  59. if (s_sp_werr)
  60. {
  61. BSTR bstr1 = 0;
  62. BSTR bstr2 = 0;
  63. SCODE sc;
  64. sc = s_sp_werr->GetFacilityCodeText( hr,
  65. 0,
  66. 0,
  67. &bstr1 );
  68. if( sc != S_OK )
  69. {
  70. bstr2 = L"Unknown Error";
  71. }
  72. sc = s_sp_werr->GetErrorCodeText( hr,
  73. 0,
  74. 0,
  75. &bstr2 );
  76. if( sc != S_OK )
  77. {
  78. bstr2 = L"Unknown Code";
  79. }
  80. mfn_Log(
  81. L"%s %s: %s(hr=0x%08lx)",
  82. pwszMessage,
  83. (LPCWSTR) bstr1,
  84. (LPCWSTR) bstr2,
  85. hr
  86. );
  87. SysFreeString( bstr1 );
  88. SysFreeString( bstr2 );
  89. }
  90. else
  91. {
  92. mfn_Log(
  93. L"%s (hr=0x%08lx)",
  94. pwszMessage,
  95. hr
  96. );
  97. }
  98. }
  99. VOID
  100. NLBHost::mfn_Log(
  101. LPCWSTR pwszMessage,
  102. ...
  103. )
  104. {
  105. WCHAR wszBuffer[1024];
  106. wszBuffer[0] = 0;
  107. va_list arglist;
  108. va_start (arglist, pwszMessage);
  109. int cch = vswprintf(wszBuffer, pwszMessage, arglist);
  110. va_end (arglist);
  111. m_pfnLogger(m_pLoggerContext, wszBuffer);
  112. }
  113. NLBHost::NLBHost(
  114. const WCHAR * pBindString,
  115. const WCHAR * pFriendlyName,
  116. PFN_LOGGER pfnLogger,
  117. PVOID pLoggerContext
  118. )
  119. /*++
  120. Routine Description:
  121. Constructor for NLBHost.
  122. The constructor does not initiate any connections to the host. Connections
  123. to the host are initiated on demand (based on method calls).
  124. Arguments:
  125. pBindString - String used to connect to the remote host.
  126. pFriendlyName - Descriptive name of the host. Used for logging.
  127. pfnLogger - Function called to log textual information.
  128. pLoggerContext - Caller's context, passed in calls to pfnLogger
  129. --*/
  130. {
  131. m_BindString = pBindString; // implicit copy
  132. m_FriendlyName = pFriendlyName; // implicit copy
  133. m_pfnLogger = pfnLogger;
  134. m_pLoggerContext = pLoggerContext;
  135. if (InterlockedIncrement(&s_InstanceCount) == 1)
  136. {
  137. mfn_InitializeStaticFields();
  138. }
  139. InitializeCriticalSection(&m_Lock);
  140. mfn_Log(
  141. L"NLBHost(BindString=%s, FriendlyName=%s) constructor succeeded.",
  142. (LPCWSTR) pBindString,
  143. (LPCWSTR) pFriendlyName
  144. );
  145. }
  146. NLBHost::~NLBHost()
  147. /*++
  148. Routine Description:
  149. Destructor for NLBHost.
  150. --*/
  151. {
  152. mfn_Log(L"NLBHost distructor(%s).", (LPCWSTR) m_FriendlyName);
  153. ASSERT(m_fProcessing == FALSE); // Shouldn't be doing any processing when
  154. // calling the distructor.
  155. if (InterlockedDecrement(&s_InstanceCount)==0)
  156. {
  157. mfn_DeinitializeStaticFields();
  158. }
  159. DeleteCriticalSection(&m_Lock);
  160. }
  161. UINT
  162. NLBHost::Ping(
  163. VOID
  164. )
  165. {
  166. if (s_FatalError) return ERROR_INTERNAL_ERROR;
  167. return mfn_ping();
  168. }
  169. UINT
  170. NLBHost::GetHostInformation(
  171. OUT HostInformation **ppHostInfo
  172. )
  173. {
  174. UINT Status;
  175. HostInformation *pHostInfo = new HostInformation;
  176. BOOL fConnected = FALSE;
  177. NicInformation NicInfo;
  178. if (s_FatalError) return ERROR_INTERNAL_ERROR;
  179. pHostInfo = new HostInformation;
  180. if (pHostInfo == NULL)
  181. {
  182. Status = ERROR_OUTOFMEMORY;
  183. goto end;
  184. }
  185. //
  186. // Connect to the host.
  187. //
  188. Status = mfn_connect();
  189. if (!NLBH_SUCCESS(Status)) goto end;
  190. fConnected = TRUE;
  191. #if 0
  192. //
  193. // Now find the instance and execute the method to get the host info.
  194. //
  195. mfn_find_host_instance();
  196. ... stuff parameters ...
  197. mfn_execute_method();
  198. #endif //
  199. pHostInfo->MachineName = L"ACME-Machine-Name";
  200. NicInfo.fullNicName = L"ACME Full Nic Name";
  201. NicInfo.adapterGuid = L"8829d17b-b0b7-4ce8-ba50-71af38792a6f";
  202. NicInfo.friendlyName = L"ACME Friendly Name";
  203. pHostInfo->nicInformation.push_back(NicInfo);
  204. NicInfo.fullNicName = L"ACME2 Full Nic Name";
  205. NicInfo.adapterGuid = L"fa770233-31c3-4475-aa96-1190058d326a";
  206. NicInfo.friendlyName = L"ACME2 Friendly Name";
  207. pHostInfo->nicInformation.push_back(NicInfo);
  208. end:
  209. if (fConnected)
  210. {
  211. mfn_disconnect();
  212. }
  213. if (!NLBH_SUCCESS(Status))
  214. {
  215. if (pHostInfo != NULL)
  216. {
  217. delete pHostInfo;
  218. }
  219. pHostInfo = NULL;
  220. }
  221. *ppHostInfo = pHostInfo;
  222. return Status;
  223. }
  224. //
  225. // Configuration operations:
  226. //
  227. UINT
  228. NLBHost::GetClusterConfiguration(
  229. IN const WCHAR* pNicGuid,
  230. OUT PMGR_RAW_CLUSTER_CONFIGURATION pClusterConfig,
  231. OUT UINT * pGenerationId
  232. )
  233. {
  234. if (s_FatalError) return ERROR_INTERNAL_ERROR;
  235. mfn_Log(
  236. L"NLBHost -- getting cluster configuration on NIC (%s).",
  237. pNicGuid
  238. );
  239. *pGenerationId = 1;
  240. return 0;
  241. }
  242. UINT
  243. NLBHost::SetClusterConfiguration(
  244. IN const WCHAR * pNicGuid,
  245. IN const PMGR_RAW_CLUSTER_CONFIGURATION pClusterConfig,
  246. IN UINT GenerationId,
  247. OUT UINT * pRequestId
  248. )
  249. {
  250. if (s_FatalError) return ERROR_INTERNAL_ERROR;
  251. mfn_Log(
  252. L"NLBHost -- setting cluster configuration on NIC (%s).",
  253. pNicGuid
  254. );
  255. *pRequestId = 123;
  256. return STATUS_PENDING;
  257. }
  258. UINT
  259. NLBHost::GetAsyncResult(
  260. IN UINT RequestId,
  261. OUT UINT * pGenerationId,
  262. OUT UINT * pResultCode,
  263. OUT _bstr_t * pResultText
  264. )
  265. {
  266. if (s_FatalError) return ERROR_INTERNAL_ERROR;
  267. mfn_Log(
  268. L"NLBHost -- checking result of Async operation %d\n",
  269. RequestId
  270. );
  271. *pGenerationId = 1;
  272. *pResultCode = 1;
  273. *pResultText = L"Result";
  274. return 0;
  275. }
  276. UINT
  277. NLBHost::mfn_connect(
  278. VOID
  279. )
  280. {
  281. UINT Status = ERROR_INTERNAL_ERROR;
  282. HRESULT hr;
  283. _bstr_t serverPath;
  284. hr = CoCreateInstance(CLSID_WbemLocator, 0,
  285. CLSCTX_INPROC_SERVER,
  286. IID_IWbemLocator,
  287. (LPVOID *) &m_sp_pwl);
  288. if (FAILED(hr))
  289. {
  290. mfn_LogHr(L"CoCreateInstance IWebmLocator failed", hr);
  291. m_sp_pwl = NULL;
  292. goto end;
  293. }
  294. //
  295. serverPath = _bstr_t(L"\\\\") + m_BindString + L"\\root\\microsoftnlb";
  296. hr = m_sp_pwl->ConnectServer(
  297. serverPath,
  298. NULL, // strUser,
  299. NULL, // strPassword,
  300. NULL,
  301. 0,
  302. NULL,
  303. NULL,
  304. &m_sp_pws
  305. );
  306. // these have been found to be special cases where retrying may help.
  307. if( ( hr == 0x800706bf ) || ( hr == 0x80070767 ) || ( hr == 0x80070005 ) )
  308. {
  309. int delay = 250; // milliseconds
  310. int timesToRetry = 20;
  311. for( int i = 0; i < timesToRetry; ++i )
  312. {
  313. Sleep(delay);
  314. mfn_Log(L"connectserver recoverable failure, retrying.");
  315. hr = m_sp_pwl->ConnectServer(
  316. serverPath,
  317. NULL, // strUser,
  318. NULL, // strPassword,
  319. NULL,
  320. 0,
  321. NULL,
  322. NULL,
  323. &m_sp_pws );
  324. if( !FAILED( hr) )
  325. {
  326. break;
  327. }
  328. }
  329. }
  330. else if ( hr == 0x80041064 )
  331. {
  332. // trying to connect to local machine. Cannot use credentials.
  333. mfn_Log(L"Connecting to self. Retrying without using credentials");
  334. hr = m_sp_pwl->ConnectServer(
  335. serverPath,
  336. NULL,
  337. NULL,
  338. 0,
  339. NULL,
  340. 0,
  341. 0,
  342. &m_sp_pws
  343. );
  344. }
  345. if (FAILED(hr))
  346. {
  347. mfn_LogHr(L"Error connecting to server", hr);
  348. m_sp_pws = NULL;
  349. goto end;
  350. }
  351. else
  352. {
  353. mfn_Log(L"Successfully connected to server %s", serverPath);
  354. }
  355. // Set the proxy so that impersonation of the client occurs.
  356. //
  357. hr = CoSetProxyBlanket(
  358. m_sp_pws,
  359. RPC_C_AUTHN_WINNT,
  360. RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_NAME,
  361. COLE_DEFAULT_PRINCIPAL, // NULL,
  362. RPC_C_AUTHN_LEVEL_DEFAULT,
  363. RPC_C_IMP_LEVEL_IMPERSONATE,
  364. COLE_DEFAULT_AUTHINFO, // NULL,
  365. EOAC_DEFAULT // EOAC_NONE
  366. );
  367. if (FAILED(hr))
  368. {
  369. mfn_LogHr(L"Error setting proxy blanket", hr);
  370. goto end;
  371. }
  372. else
  373. {
  374. mfn_Log(L"Successfully set up proxy settings.");
  375. }
  376. Status = ERROR_SUCCESS;
  377. end:
  378. if (!NLBH_SUCCESS(Status))
  379. {
  380. if (m_sp_pws != NULL)
  381. {
  382. // Smart pointer.
  383. m_sp_pws = NULL;
  384. }
  385. if (m_sp_pwl != NULL)
  386. {
  387. // Smart pointer.
  388. m_sp_pwl = NULL;
  389. }
  390. }
  391. return Status;
  392. }
  393. VOID
  394. NLBHost::mfn_disconnect(
  395. VOID
  396. )
  397. {
  398. mfn_Log(L"Disconnecting from host %s", m_BindString);
  399. if (m_sp_pws != NULL)
  400. {
  401. // Smart pointer
  402. m_sp_pws = NULL;
  403. }
  404. if (m_sp_pwl != NULL)
  405. {
  406. // Smart pointer
  407. m_sp_pwl = NULL;
  408. }
  409. }
  410. VOID
  411. NLBHost::mfn_InitializeStaticFields(
  412. VOID
  413. )
  414. {
  415. s_FatalError = TRUE;
  416. // Initialize com.
  417. //
  418. HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
  419. if ( FAILED(hr) )
  420. {
  421. mfn_Log(L"Failed to initialize COM library (hr=0x%08lx)", hr);
  422. goto end;
  423. }
  424. s_ComInitialized = TRUE;
  425. //
  426. // Initialize Winsock
  427. //
  428. int err = WSAStartup(MAKEWORD(2,2), &s_WsaData);
  429. mfn_Log(L"Initializing Winsock");
  430. err = WSAStartup(MAKEWORD(2,2), &s_WsaData);
  431. if (err) {
  432. mfn_Log(L"PING_WSASTARTUP_FAILED %d", GetLastError());
  433. goto end;
  434. }
  435. s_WsaInitialized = TRUE;
  436. s_FatalError = FALSE;
  437. //
  438. // Get some WMI interface pointers...
  439. //
  440. SCODE sc = CoCreateInstance(
  441. CLSID_WbemStatusCodeText,
  442. 0,
  443. CLSCTX_INPROC_SERVER,
  444. IID_IWbemStatusCodeText,
  445. (LPVOID *) &s_sp_werr
  446. );
  447. if( sc != S_OK )
  448. {
  449. s_sp_werr = NULL;
  450. mfn_Log(L"CoCreateInstance IWbemStatusCodeText failure\n");
  451. }
  452. end:
  453. if (s_FatalError)
  454. {
  455. mfn_DeinitializeStaticFields();
  456. }
  457. }
  458. VOID
  459. NLBHost::mfn_DeinitializeStaticFields(
  460. VOID
  461. )
  462. {
  463. if (s_sp_werr != NULL)
  464. {
  465. s_sp_werr = NULL; // Smart pointer
  466. }
  467. if (s_WsaInitialized)
  468. {
  469. mfn_Log(L"Deinitializing Winsock");
  470. WSACleanup();
  471. s_WsaInitialized = FALSE;
  472. }
  473. if (s_ComInitialized)
  474. {
  475. mfn_Log(L"Deinitializing COM");
  476. CoUninitialize();
  477. s_ComInitialized = FALSE;
  478. }
  479. }