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.

504 lines
16 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // CClusNet.cpp
  7. //
  8. // Description:
  9. // Contains the definition of the CClusNet class.
  10. //
  11. // Maintained By:
  12. // Vij Vasu (Vvasu) 08-MAR-2000
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. //////////////////////////////////////////////////////////////////////////////
  16. // Include Files
  17. //////////////////////////////////////////////////////////////////////////////
  18. // The precompiled header.
  19. #include "pch.h"
  20. // The header for this file
  21. #include "CClusNet.h"
  22. extern "C"
  23. {
  24. // Required by the winsock functions
  25. #include <winsock2.h>
  26. // For the winsock MigrateWinsockConfiguration function.
  27. #include <wsasetup.h>
  28. // For the winsock WSHGetWinsockMapping function.
  29. #include <wsahelp.h>
  30. }
  31. // For the definition of SOCKADDR_CLUSTER
  32. #include <wsclus.h>
  33. //////////////////////////////////////////////////////////////////////////////
  34. // Macros
  35. //////////////////////////////////////////////////////////////////////////////
  36. // The name of the ClusNet service
  37. #define CLUSNET_SERVICE_NAME L"ClusNet"
  38. // Registry location of the ClusNet winsock entries key
  39. #define CLUSNET_WINSOCK_KEY L"System\\CurrentControlSet\\Services\\ClusNet\\Parameters\\Winsock"
  40. // Name of the ClusNet winsock mapping registry value
  41. #define CLUSNET_WINSOCK_MAPPING L"Mapping"
  42. // Name of the ClusNet winsock minimum socket address length registry value
  43. #define CLUSNET_WINSOCK_MINSOCKADDRLEN L"MinSockaddrLength"
  44. // Name of the ClusNet winsock maximum socket address length registry value
  45. #define CLUSNET_WINSOCK_MAXSOCKADDRLEN L"MaxSockaddrLength"
  46. // Name of the DLL containing the WinSock cluster helper functions
  47. #define WSHCLUS_DLL_NAME L"WSHClus.dll"
  48. // Name of the winsock parameters key.
  49. #define WINSOCK_PARAMS_KEY L"System\\CurrentControlSet\\Services\\WinSock\\Parameters"
  50. // Name of the winsock transports registry key.
  51. #define WINSOCK_PARAMS_TRANSPORT_VAL L"Transports"
  52. //////////////////////////////////////////////////////////////////////////////
  53. //++
  54. //
  55. // CClusNet::CClusNet()
  56. //
  57. // Description:
  58. // Constructor of the CClusNet class
  59. //
  60. // Arguments:
  61. // pbcaParentActionIn
  62. // Pointer to the base cluster action of which this action is a part.
  63. //
  64. // Return Value:
  65. // None.
  66. //
  67. // Exceptions Thrown:
  68. // CAssert
  69. // If the parameters are incorrect.
  70. //
  71. // Any exceptions thrown by underlying functions
  72. //
  73. //--
  74. //////////////////////////////////////////////////////////////////////////////
  75. CClusNet::CClusNet(
  76. CBaseClusterAction * pbcaParentActionIn
  77. )
  78. : m_cservClusNet( CLUSNET_SERVICE_NAME )
  79. , m_pbcaParentAction( pbcaParentActionIn )
  80. {
  81. BCATraceScope( "" );
  82. if ( m_pbcaParentAction == NULL)
  83. {
  84. BCATraceMsg( "Pointers to the parent action is NULL. Throwing exception." );
  85. THROW_ASSERT(
  86. E_INVALIDARG
  87. , "CClusNet::CClusNet() => Required input pointer in NULL"
  88. );
  89. } // if: the parent action pointer is NULL
  90. } //*** CClusNet::CClusNet()
  91. //////////////////////////////////////////////////////////////////////////////
  92. //++
  93. //
  94. // CClusNet::~CClusNet( void )
  95. //
  96. // Description:
  97. // Destructor of the CClusNet class.
  98. //
  99. // Arguments:
  100. // None.
  101. //
  102. // Return Value:
  103. // None.
  104. //
  105. // Exceptions Thrown:
  106. // Any exceptions thrown by underlying functions
  107. //
  108. //--
  109. //////////////////////////////////////////////////////////////////////////////
  110. CClusNet::~CClusNet( void )
  111. {
  112. BCATraceScope( "" );
  113. } //*** CClusNet::~CClusNet()
  114. //////////////////////////////////////////////////////////////////////////////
  115. //++
  116. //
  117. // void
  118. // CClusNet::ConfigureService()
  119. //
  120. // Description:
  121. // Installs the cluster network transport.
  122. //
  123. // Arguments:
  124. // None.
  125. //
  126. // Return Value:
  127. // None.
  128. //
  129. // Exceptions Thrown:
  130. // CRuntimeError
  131. // If any of the APIs fail.
  132. //
  133. // Any that are thrown by the underlying functions.
  134. //
  135. //--
  136. //////////////////////////////////////////////////////////////////////////////
  137. void
  138. CClusNet::ConfigureService( void )
  139. {
  140. BCATraceScope( "" );
  141. DWORD dwMappingSize = 0;
  142. DWORD dwSocketAddrLen = sizeof( SOCKADDR_CLUSTER );
  143. DWORD dwError = ERROR_SUCCESS;
  144. WSA_SETUP_DISPOSITION wsdDisposition;
  145. {
  146. CStatusReport srCreatingClusNet(
  147. PbcaGetParent()->PBcaiGetInterfacePointer()
  148. , TASKID_Major_Configure_Cluster_Services
  149. , TASKID_Minor_Creating_ClusNet_Service
  150. , 0, 1
  151. , IDS_TASK_CREATING_CLUSNET
  152. );
  153. LogMsg( "Creating the Cluster Network Provider." );
  154. // Send the next step of this status report.
  155. srCreatingClusNet.SendNextStep( S_OK );
  156. // Create the clusnet service.
  157. m_cservClusNet.Create( m_pbcaParentAction->HGetMainInfFileHandle() );
  158. LogMsg( "Setting Cluster Network Provider service parameters." );
  159. CRegistryKey regClusNetWinsockKey(
  160. HKEY_LOCAL_MACHINE
  161. , CLUSNET_WINSOCK_KEY
  162. , KEY_ALL_ACCESS
  163. );
  164. //
  165. // Install the cluster network provider. A part of the required registry entries have
  166. // already been made when the service was created.
  167. //
  168. {
  169. //
  170. // The WSHClus DLL has to be loaded dynamically. Due to the decision to put the
  171. // code for the client side and the server side of ClusCfg in the same DLL, we
  172. // cannot implicitly link to any DLL that is not present on the client side even
  173. // if the functions in the DLL are called only on the server side.
  174. //
  175. typedef CSmartResource<
  176. CHandleTrait<
  177. HMODULE
  178. , BOOL
  179. , FreeLibrary
  180. , reinterpret_cast< HMODULE >( NULL )
  181. >
  182. > SmartModuleHandle;
  183. // Type of the WSHGetWinsockMapping function.
  184. typedef DWORD ( * WSHGetWinsockMappingFunctionType )( PWINSOCK_MAPPING, DWORD );
  185. // Pointer to the WSHGetWinsockMapping function.
  186. WSHGetWinsockMappingFunctionType pWSHGetWinsockMapping;
  187. // Get the full path the WSHClus DLL.
  188. CStr strWSHClusDllPath( m_pbcaParentAction->RStrGetClusterInstallDirectory() );
  189. strWSHClusDllPath += L"\\" WSHCLUS_DLL_NAME;
  190. // Load the library and store the handle in a smart pointer for safe release.
  191. SmartModuleHandle smhWSHClusDll( LoadLibrary( strWSHClusDllPath.PszData() ) );
  192. if ( smhWSHClusDll.FIsInvalid() )
  193. {
  194. dwError = TW32( GetLastError() );
  195. LogMsg( "LoadLibrary() retured error %#08x trying to load '%s'. Aborting.", dwError, strWSHClusDllPath.PszData() );
  196. BCATraceMsg2( "LoadLibrary() retured error %#08x trying to load '%s'. Throwing an exception.", dwError, strWSHClusDllPath.PszData() );
  197. THROW_RUNTIME_ERROR(
  198. HRESULT_FROM_WIN32( dwError )
  199. , IDS_ERROR_CLUSNET_PROV_INSTALL
  200. );
  201. } // if: LoadLibrary failed.
  202. pWSHGetWinsockMapping = reinterpret_cast< WSHGetWinsockMappingFunctionType >(
  203. GetProcAddress( smhWSHClusDll.HHandle(), "WSHGetWinsockMapping" )
  204. );
  205. if ( pWSHGetWinsockMapping == NULL )
  206. {
  207. dwError = TW32( GetLastError() );
  208. BCATraceMsg1( "GetProcAddress() retured error %#08x. Throwing an exception.", dwError );
  209. THROW_RUNTIME_ERROR(
  210. HRESULT_FROM_WIN32( dwError )
  211. , IDS_ERROR_CLUSNET_PROV_INSTALL
  212. );
  213. } // if: GetProcAddress() failed
  214. // Get WinSock mapping data
  215. dwMappingSize = pWSHGetWinsockMapping( NULL, 0 );
  216. CSmartGenericPtr< CPtrTrait< WINSOCK_MAPPING > >
  217. swmWinSockMapping( reinterpret_cast< WINSOCK_MAPPING * >( new BYTE[ dwMappingSize ] ) );
  218. if ( swmWinSockMapping.FIsEmpty() )
  219. {
  220. LogMsg( "A memory allocation failure occurred while setting Cluster Network Provider service parameters." );
  221. BCATraceMsg1( "Could not allocate %d bytes of memory for WinSock mapping. Throwing exception.", dwMappingSize );
  222. THROW_RUNTIME_ERROR(
  223. E_OUTOFMEMORY
  224. , IDS_ERROR_CLUSNET_PROV_INSTALL
  225. );
  226. } // if: we could not allocate memory for the winsock mapping.
  227. // Get the winsock mapping.
  228. dwMappingSize = pWSHGetWinsockMapping( swmWinSockMapping.PMem(), dwMappingSize );
  229. // Write it to the registry.
  230. BCATraceMsg2( "Writing registry value HKLM\\%s\\%s.", CLUSNET_WINSOCK_KEY, CLUSNET_WINSOCK_MAPPING );
  231. regClusNetWinsockKey.SetValue(
  232. CLUSNET_WINSOCK_MAPPING
  233. , REG_BINARY
  234. , reinterpret_cast< const BYTE *>( swmWinSockMapping.PMem() )
  235. , dwMappingSize
  236. );
  237. }
  238. //
  239. // Write the minimum and maximum socket address length to the registry.
  240. //
  241. BCATraceMsg2( "Writing registry value HKLM\\%s\\%s.", CLUSNET_WINSOCK_KEY, CLUSNET_WINSOCK_MINSOCKADDRLEN );
  242. regClusNetWinsockKey.SetValue(
  243. CLUSNET_WINSOCK_MINSOCKADDRLEN
  244. , REG_DWORD
  245. , reinterpret_cast< const BYTE *>( &dwSocketAddrLen )
  246. , sizeof( dwSocketAddrLen )
  247. );
  248. BCATraceMsg2( "Writing registry value HKLM\\%s\\%s.", CLUSNET_WINSOCK_KEY, CLUSNET_WINSOCK_MAXSOCKADDRLEN );
  249. regClusNetWinsockKey.SetValue(
  250. CLUSNET_WINSOCK_MAXSOCKADDRLEN
  251. , REG_DWORD
  252. , reinterpret_cast< const BYTE *>( &dwSocketAddrLen )
  253. , sizeof( dwSocketAddrLen )
  254. );
  255. //
  256. // Poke winsock to update the Winsock2 config
  257. //
  258. BCATraceMsg( "About to migrate winsock configuration." );
  259. dwError = TW32( MigrateWinsockConfiguration( &wsdDisposition, NULL, NULL ) );
  260. if ( dwError != ERROR_SUCCESS )
  261. {
  262. LogMsg( "Error %#08x occurred while trying to migrate the Winsock Configuration.", dwError );
  263. BCATraceMsg1( "MigrateWinsockConfiguration has returned error %#08x. Throwing exception.", dwError );
  264. THROW_RUNTIME_ERROR(
  265. HRESULT_FROM_WIN32( dwError )
  266. , IDS_ERROR_CLUSNET_PROV_INSTALL
  267. );
  268. } // if: an error occurred poking winsock.
  269. // Send the last step of this status report.
  270. srCreatingClusNet.SendNextStep( S_OK );
  271. }
  272. {
  273. UINT cQueryCount = 10;
  274. CStatusReport srStartingClusNet(
  275. PbcaGetParent()->PBcaiGetInterfacePointer()
  276. , TASKID_Major_Configure_Cluster_Services
  277. , TASKID_Minor_Starting_ClusNet_Service
  278. , 0, cQueryCount + 2 // we will send at most cQueryCount reports while waiting for the service to start (the two extra sends are below)
  279. , IDS_TASK_STARTING_CLUSNET
  280. );
  281. // Send the next step of this status report.
  282. srStartingClusNet.SendNextStep( S_OK );
  283. // Start the service.
  284. m_cservClusNet.Start(
  285. m_pbcaParentAction->HGetSCMHandle()
  286. , true // wait for the service to start
  287. , 500 // wait 500ms between queries for status.
  288. , cQueryCount // query cQueryCount times.
  289. , &srStartingClusNet // status report to be sent while waiting for the service to start
  290. );
  291. // Send the last step of this status report.
  292. srStartingClusNet.SendLastStep( S_OK );
  293. }
  294. } //*** CClusNet::ConfigureService()
  295. //////////////////////////////////////////////////////////////////////////////
  296. //++
  297. //
  298. // void
  299. // CClusNet::CleanupService()
  300. //
  301. // Description:
  302. // Remove ClusNet from the Winsock transports list. Delete the service.
  303. //
  304. // Arguments:
  305. // None.
  306. //
  307. // Return Value:
  308. // None.
  309. //
  310. // Exceptions Thrown:
  311. // CRuntimeError
  312. // If any of the APIs fail.
  313. //
  314. // Any that are thrown by the underlying functions.
  315. //
  316. //--
  317. //////////////////////////////////////////////////////////////////////////////
  318. void
  319. CClusNet::CleanupService( void )
  320. {
  321. BCATraceScope( "" );
  322. DWORD dwError = ERROR_SUCCESS;
  323. WCHAR * pmszTransportList = NULL;
  324. DWORD cbBufSize = 0;
  325. DWORD cbBufRemaining = 0;
  326. UINT uiClusNetNameLenPlusOne = wcslen( CLUSNET_SERVICE_NAME ) + 1;
  327. UINT cbClusNetNameSize = uiClusNetNameLenPlusOne * sizeof( WCHAR );
  328. WSA_SETUP_DISPOSITION wsdDisposition;
  329. LogMsg( "Stopping the Cluster Network Provider service." );
  330. // Stop the service.
  331. m_cservClusNet.Stop(
  332. m_pbcaParentAction->HGetSCMHandle()
  333. , 500 // wait 500ms between queries for status.
  334. , 10 // query 10 times.
  335. );
  336. LogMsg( "Cleaning up the Cluster Network Provider service." );
  337. // Clean up the ClusNet service.
  338. m_cservClusNet.Cleanup( m_pbcaParentAction->HGetMainInfFileHandle() );
  339. // Open the winsock registry key.
  340. CRegistryKey regWinsockKey(
  341. HKEY_LOCAL_MACHINE
  342. , WINSOCK_PARAMS_KEY
  343. , KEY_ALL_ACCESS
  344. );
  345. //
  346. // Remove the cluster network provider from the Winsock transports list.
  347. //
  348. BCATraceMsg( "Reading the Winsock transport list." );
  349. regWinsockKey.QueryValue(
  350. WINSOCK_PARAMS_TRANSPORT_VAL
  351. , reinterpret_cast< LPBYTE * >( &pmszTransportList )
  352. , &cbBufSize
  353. );
  354. //
  355. // Assign the pointer to the allocated buffer to a smart pointer for automatic
  356. // release.
  357. //
  358. SmartSz sszTransports( pmszTransportList );
  359. // Remove the string "ClusNet" from the multisz list.
  360. BCATraceMsg( "Removing ClusNet from the Winsock transport list." );
  361. cbBufRemaining = cbBufSize;
  362. while ( *pmszTransportList != L'\0' )
  363. {
  364. UINT uiCurStrLenPlusOne = wcslen( pmszTransportList ) + 1;
  365. // If this string is ClusNet
  366. if ( ( uiCurStrLenPlusOne == uiClusNetNameLenPlusOne )
  367. && ( _wcsicmp( pmszTransportList, CLUSNET_SERVICE_NAME ) == 0 )
  368. )
  369. {
  370. // Remove this string from the list
  371. cbBufSize -= cbClusNetNameSize;
  372. // Decrement the amount of buffer yet unparsed.
  373. cbBufRemaining -= cbClusNetNameSize;
  374. MoveMemory(
  375. pmszTransportList
  376. , pmszTransportList + uiClusNetNameLenPlusOne
  377. , cbBufRemaining
  378. );
  379. } // if: this string is "ClusNet"
  380. else
  381. {
  382. // Decrement the amount of buffer yet unparsed.
  383. cbBufRemaining -= uiCurStrLenPlusOne * sizeof( *pmszTransportList );
  384. // Move to the next string
  385. pmszTransportList += uiCurStrLenPlusOne;
  386. } // else: this string is not "ClusNet"
  387. } // while: the transport list has not been completely parsed.
  388. BCATraceMsg( "Writing the Winsock transport list back to the registry." );
  389. // Write the new list back into the registry.
  390. regWinsockKey.SetValue(
  391. WINSOCK_PARAMS_TRANSPORT_VAL
  392. , REG_MULTI_SZ
  393. , reinterpret_cast< BYTE * >( sszTransports.PMem() )
  394. , cbBufSize
  395. );
  396. //
  397. // Poke winsock to update the Winsock2 config
  398. //
  399. BCATraceMsg( "About to migrate winsock configuration." );
  400. dwError = TW32( MigrateWinsockConfiguration( &wsdDisposition, NULL, NULL ) );
  401. if ( dwError != ERROR_SUCCESS )
  402. {
  403. LogMsg( "Error %#08x occurred while trying to migrate the Winsock Configuration.", dwError );
  404. BCATraceMsg1( "MigrateWinsockConfiguration has returned error %#08x. Throwing exception.", dwError );
  405. THROW_RUNTIME_ERROR(
  406. HRESULT_FROM_WIN32( dwError )
  407. , IDS_ERROR_CLUSNET_PROV_INSTALL
  408. );
  409. } // if: an error occurred poking winsock.
  410. } //*** CClusNet::CleanupService()