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.

507 lines
16 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999-2001 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. // David Potter (DavidP) 14-JUN-2001
  13. // Vij Vasu (Vvasu) 08-MAR-2000
  14. //
  15. //////////////////////////////////////////////////////////////////////////////
  16. //////////////////////////////////////////////////////////////////////////////
  17. // Include Files
  18. //////////////////////////////////////////////////////////////////////////////
  19. // The precompiled header.
  20. #include "Pch.h"
  21. // The header for this file
  22. #include "CClusNet.h"
  23. extern "C"
  24. {
  25. // Required by the winsock functions
  26. #include <winsock2.h>
  27. // For the winsock MigrateWinsockConfiguration function.
  28. #include <wsasetup.h>
  29. // For the winsock WSHGetWinsockMapping function.
  30. #include <wsahelp.h>
  31. }
  32. // For the definition of SOCKADDR_CLUSTER
  33. #include <wsclus.h>
  34. //////////////////////////////////////////////////////////////////////////////
  35. // Macros
  36. //////////////////////////////////////////////////////////////////////////////
  37. // The name of the ClusNet service
  38. #define CLUSNET_SERVICE_NAME L"ClusNet"
  39. // Registry location of the ClusNet winsock entries key
  40. #define CLUSNET_WINSOCK_KEY L"System\\CurrentControlSet\\Services\\ClusNet\\Parameters\\Winsock"
  41. // Name of the ClusNet winsock mapping registry value
  42. #define CLUSNET_WINSOCK_MAPPING L"Mapping"
  43. // Name of the ClusNet winsock minimum socket address length registry value
  44. #define CLUSNET_WINSOCK_MINSOCKADDRLEN L"MinSockaddrLength"
  45. // Name of the ClusNet winsock maximum socket address length registry value
  46. #define CLUSNET_WINSOCK_MAXSOCKADDRLEN L"MaxSockaddrLength"
  47. // Name of the DLL containing the WinSock cluster helper functions
  48. #define WSHCLUS_DLL_NAME L"WSHClus.dll"
  49. // Name of the winsock parameters key.
  50. #define WINSOCK_PARAMS_KEY L"System\\CurrentControlSet\\Services\\WinSock\\Parameters"
  51. // Name of the winsock transports registry key.
  52. #define WINSOCK_PARAMS_TRANSPORT_VAL L"Transports"
  53. //////////////////////////////////////////////////////////////////////////////
  54. //++
  55. //
  56. // CClusNet::CClusNet
  57. //
  58. // Description:
  59. // Constructor of the CClusNet class
  60. //
  61. // Arguments:
  62. // pbcaParentActionIn
  63. // Pointer to the base cluster action of which this action is a part.
  64. //
  65. // Return Value:
  66. // None.
  67. //
  68. // Exceptions Thrown:
  69. // CAssert
  70. // If the parameters are incorrect.
  71. //
  72. // Any exceptions thrown by underlying functions
  73. //
  74. //--
  75. //////////////////////////////////////////////////////////////////////////////
  76. CClusNet::CClusNet(
  77. CBaseClusterAction * pbcaParentActionIn
  78. )
  79. : m_cservClusNet( CLUSNET_SERVICE_NAME )
  80. , m_pbcaParentAction( pbcaParentActionIn )
  81. {
  82. TraceFunc( "" );
  83. if ( m_pbcaParentAction == NULL)
  84. {
  85. LogMsg( "[BC] Pointers to the parent action is NULL. Throwing exception." );
  86. THROW_ASSERT(
  87. E_INVALIDARG
  88. , "CClusNet::CClusNet() => Required input pointer in NULL"
  89. );
  90. } // if: the parent action pointer is NULL
  91. TraceFuncExit();
  92. } //*** CClusNet::CClusNet
  93. //////////////////////////////////////////////////////////////////////////////
  94. //++
  95. //
  96. // CClusNet::~CClusNet
  97. //
  98. // Description:
  99. // Destructor of the CClusNet class.
  100. //
  101. // Arguments:
  102. // None.
  103. //
  104. // Return Value:
  105. // None.
  106. //
  107. // Exceptions Thrown:
  108. // Any exceptions thrown by underlying functions
  109. //
  110. //--
  111. //////////////////////////////////////////////////////////////////////////////
  112. CClusNet::~CClusNet( void )
  113. {
  114. TraceFunc( "" );
  115. TraceFuncExit();
  116. } //*** CClusNet::~CClusNet
  117. //////////////////////////////////////////////////////////////////////////////
  118. //++
  119. //
  120. // CClusNet::ConfigureService
  121. //
  122. // Description:
  123. // Installs the cluster network transport.
  124. //
  125. // Arguments:
  126. // None.
  127. //
  128. // Return Value:
  129. // None.
  130. //
  131. // Exceptions Thrown:
  132. // CRuntimeError
  133. // If any of the APIs fail.
  134. //
  135. // Any that are thrown by the underlying functions.
  136. //
  137. //--
  138. //////////////////////////////////////////////////////////////////////////////
  139. void
  140. CClusNet::ConfigureService( void )
  141. {
  142. TraceFunc( "" );
  143. DWORD dwMappingSize = 0;
  144. DWORD dwSocketAddrLen = sizeof( SOCKADDR_CLUSTER );
  145. DWORD sc = ERROR_SUCCESS;
  146. WSA_SETUP_DISPOSITION wsdDisposition;
  147. {
  148. CStatusReport srCreatingClusNet(
  149. PbcaGetParent()->PBcaiGetInterfacePointer()
  150. , TASKID_Major_Configure_Cluster_Services
  151. , TASKID_Minor_Creating_ClusNet_Service
  152. , 0, 1
  153. , IDS_TASK_CREATING_CLUSNET
  154. );
  155. LogMsg( "[BC] Creating the Cluster Network Provider." );
  156. // Send the next step of this status report.
  157. srCreatingClusNet.SendNextStep( S_OK );
  158. // Create the clusnet service.
  159. m_cservClusNet.Create( m_pbcaParentAction->HGetMainInfFileHandle() );
  160. LogMsg( "[BC] Setting Cluster Network Provider service parameters." );
  161. CRegistryKey regClusNetWinsockKey(
  162. HKEY_LOCAL_MACHINE
  163. , CLUSNET_WINSOCK_KEY
  164. , KEY_ALL_ACCESS
  165. );
  166. //
  167. // Install the cluster network provider. A part of the required registry entries have
  168. // already been made when the service was created.
  169. //
  170. {
  171. //
  172. // The WSHClus DLL has to be loaded dynamically. Due to the decision to put the
  173. // code for the client side and the server side of ClusCfg in the same DLL, we
  174. // cannot implicitly link to any DLL that is not present on the client side even
  175. // if the functions in the DLL are called only on the server side.
  176. //
  177. typedef CSmartResource<
  178. CHandleTrait<
  179. HMODULE
  180. , BOOL
  181. , FreeLibrary
  182. , reinterpret_cast< HMODULE >( NULL )
  183. >
  184. > SmartModuleHandle;
  185. // Type of the WSHGetWinsockMapping function.
  186. typedef DWORD ( * WSHGetWinsockMappingFunctionType )( PWINSOCK_MAPPING, DWORD );
  187. // Pointer to the WSHGetWinsockMapping function.
  188. WSHGetWinsockMappingFunctionType pWSHGetWinsockMapping;
  189. // Get the full path the WSHClus DLL.
  190. CStr strWSHClusDllPath( m_pbcaParentAction->RStrGetClusterInstallDirectory() );
  191. strWSHClusDllPath += L"\\" WSHCLUS_DLL_NAME;
  192. // Load the library and store the handle in a smart pointer for safe release.
  193. SmartModuleHandle smhWSHClusDll( LoadLibrary( strWSHClusDllPath.PszData() ) );
  194. if ( smhWSHClusDll.FIsInvalid() )
  195. {
  196. sc = TW32( GetLastError() );
  197. LogMsg( "[BC] LoadLibrary() retured error %#08x trying to load '%s'. Aborting (throwing an exception).", sc, strWSHClusDllPath.PszData() );
  198. THROW_RUNTIME_ERROR(
  199. HRESULT_FROM_WIN32( sc )
  200. , IDS_ERROR_CLUSNET_PROV_INSTALL
  201. );
  202. } // if: LoadLibrary failed.
  203. pWSHGetWinsockMapping = reinterpret_cast< WSHGetWinsockMappingFunctionType >(
  204. GetProcAddress( smhWSHClusDll.HHandle(), "WSHGetWinsockMapping" )
  205. );
  206. if ( pWSHGetWinsockMapping == NULL )
  207. {
  208. sc = TW32( GetLastError() );
  209. LogMsg( "[BC] GetProcAddress() retured error %#08x trying to get the address of 'WSHGetWinsockMapping'. Throwing an exception.", sc );
  210. THROW_RUNTIME_ERROR(
  211. HRESULT_FROM_WIN32( sc )
  212. , IDS_ERROR_CLUSNET_PROV_INSTALL
  213. );
  214. } // if: GetProcAddress() failed
  215. // Get WinSock mapping data
  216. dwMappingSize = pWSHGetWinsockMapping( NULL, 0 );
  217. CSmartGenericPtr< CPtrTrait< WINSOCK_MAPPING > >
  218. swmWinSockMapping( reinterpret_cast< WINSOCK_MAPPING * >( new BYTE[ dwMappingSize ] ) );
  219. if ( swmWinSockMapping.FIsEmpty() )
  220. {
  221. LogMsg( "[BC] A memory allocation failure occurred (%d bytes) while setting Cluster Network Provider service parameters.", 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. LogMsg( "[BC] Writing registry value HKLM\\%ws\\%ws.", 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. LogMsg( "[BC] Writing registry value HKLM\\%ws\\%ws.", 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. LogMsg( "[BC] Writing registry value HKLM\\%ws\\%ws.", 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. LogMsg( "[BC] About to migrate winsock configuration." );
  259. sc = TW32( MigrateWinsockConfiguration( &wsdDisposition, NULL, NULL ) );
  260. if ( sc != ERROR_SUCCESS )
  261. {
  262. LogMsg( "[BC] Error %#08x occurred while trying to migrate the Winsock Configuration. Throwing an exception.", sc );
  263. TraceFlow1( "MigrateWinsockConfiguration has returned error %#08x. Throwing exception.", sc );
  264. THROW_RUNTIME_ERROR(
  265. HRESULT_FROM_WIN32( sc )
  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. TraceFuncExit();
  295. } //*** CClusNet::ConfigureService
  296. //////////////////////////////////////////////////////////////////////////////
  297. //++
  298. //
  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. TraceFunc( "" );
  322. DWORD sc = ERROR_SUCCESS;
  323. WCHAR * pmszTransportList = NULL;
  324. DWORD cbBufSize = 0;
  325. DWORD cbBufRemaining = 0;
  326. UINT uiClusNetNameLenPlusOne = ARRAYSIZE( CLUSNET_SERVICE_NAME );
  327. UINT cbClusNetNameSize = uiClusNetNameLenPlusOne * sizeof( WCHAR );
  328. WSA_SETUP_DISPOSITION wsdDisposition;
  329. LogMsg( "[BC] 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( "[BC] 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. LogMsg( "[BC] 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. LogMsg( "[BC] Removing ClusNet from the Winsock transport list." );
  361. cbBufRemaining = cbBufSize;
  362. while ( *pmszTransportList != L'\0' )
  363. {
  364. UINT uiCurStrLenPlusOne = (UINT) wcslen( pmszTransportList ) + 1;
  365. // If this string is ClusNet
  366. if ( ( uiCurStrLenPlusOne == uiClusNetNameLenPlusOne )
  367. && ( NStringCchCompareNoCase( pmszTransportList, uiCurStrLenPlusOne, CLUSNET_SERVICE_NAME, RTL_NUMBER_OF( 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. LogMsg( "[BC] 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. LogMsg( "[BC] About to migrate winsock configuration." );
  400. sc = TW32( MigrateWinsockConfiguration( &wsdDisposition, NULL, NULL ) );
  401. if ( sc != ERROR_SUCCESS )
  402. {
  403. LogMsg( "[BC] Error %#08x occurred while trying to migrate the Winsock Configuration. Throwing an exception.", sc );
  404. THROW_RUNTIME_ERROR(
  405. HRESULT_FROM_WIN32( sc )
  406. , IDS_ERROR_CLUSNET_PROV_INSTALL
  407. );
  408. } // if: an error occurred poking winsock.
  409. TraceFuncExit();
  410. } //*** CClusNet::CleanupService