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.

448 lines
16 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000-2002 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // CTaskUpgrade.cpp
  7. //
  8. // Description:
  9. // Implementation file for the CTaskUpgrade class.
  10. //
  11. // Header File:
  12. // CTaskUpgrade.h
  13. //
  14. // Maintained By:
  15. // David Potter (DavidP) 25-MAR-2002
  16. // Vij Vasu (Vvasu) 18-APR-2000
  17. //
  18. //////////////////////////////////////////////////////////////////////////////
  19. //////////////////////////////////////////////////////////////////////////////
  20. // Include Files
  21. //////////////////////////////////////////////////////////////////////////////
  22. // Precompiled header for this DLL.
  23. #include "Pch.h"
  24. #include <Common.h>
  25. // The header file for this module.
  26. #include "CTaskUpgrade.h"
  27. // For COM category operations
  28. #include <comcat.h>
  29. // To define guid values
  30. #include <initguid.h>
  31. // For CLSID_ClusCfgResTypeGenScript and CLSID_ClusCfgResTypeMajorityNodeSet
  32. #include <guids.h>
  33. // For CATID_ClusCfgStartupListeners
  34. #include <ClusCfgGuids.h>
  35. //////////////////////////////////////////////////////////////////////////////
  36. // Macro Definitions
  37. //////////////////////////////////////////////////////////////////////////////
  38. // Needed for tracing.
  39. DEFINE_THISCLASS( "CTaskUpgrade" )
  40. /////////////////////////////////////////////////////////////////////////////
  41. //++
  42. //
  43. // CTaskUpgrade::CTaskUpgrade
  44. //
  45. // Description:
  46. // Constructor of the CTaskUpgrade class.
  47. //
  48. // Arguments:
  49. // const CClusOCMApp & rAppIn
  50. // Reference to the CClusOCMApp object that is hosting this task.
  51. //
  52. // Return Value:
  53. // None.
  54. //
  55. //--
  56. /////////////////////////////////////////////////////////////////////////////
  57. CTaskUpgrade::CTaskUpgrade( const CClusOCMApp & rAppIn )
  58. : BaseClass( rAppIn )
  59. , m_fClusDirFound( false )
  60. {
  61. TraceFunc( "" );
  62. //
  63. // Make sure that this object is being instatiated only when required.
  64. //
  65. // Assert that this is an upgrade.
  66. Assert( rAppIn.FIsUpgrade() != false );
  67. // Assert that we will upgrade binaries only if they were previously
  68. // installed
  69. Assert( rAppIn.CisGetClusterInstallState() != eClusterInstallStateUnknown );
  70. TraceFuncExit();
  71. } //*** CTaskUpgrade::CTaskUpgrade()
  72. /////////////////////////////////////////////////////////////////////////////
  73. //++
  74. //
  75. // CTaskUpgrade::~CTaskUpgrade
  76. //
  77. // Description:
  78. // Destructor of the CTaskUpgrade class.
  79. //
  80. // Arguments:
  81. // None.
  82. //
  83. // Return Value:
  84. // None.
  85. //
  86. //--
  87. /////////////////////////////////////////////////////////////////////////////
  88. CTaskUpgrade::~CTaskUpgrade( void )
  89. {
  90. TraceFunc( "" );
  91. TraceFuncExit();
  92. } //*** CTaskUpgrade::~CTaskUpgrade()
  93. /////////////////////////////////////////////////////////////////////////////
  94. //++
  95. //
  96. // DWORD
  97. // CTaskUpgrade::DwOcCompleteInstallation
  98. //
  99. // Description:
  100. // This is a helper function that performs some of the more common
  101. // operations done by handlers of the OC_COMPLETE_INSTALLATION message.
  102. //
  103. // Registry operations, COM component registrations, creation of servies
  104. // etc. listed in the input section are processed by this function.
  105. // This function is meant to be called by derived classes only.
  106. //
  107. // Arguments:
  108. // const WCHAR * pcszInstallSectionNameIn
  109. // Name of the section which contains details registry entries,
  110. // COM components, etc., that need to be set up.
  111. //
  112. // Return Value:
  113. // NO_ERROR if all went well.
  114. // Other Win32 error codes on failure.
  115. //
  116. //--
  117. /////////////////////////////////////////////////////////////////////////////
  118. DWORD
  119. CTaskUpgrade::DwOcCompleteInstallation( const WCHAR * pcszInstallSectionNameIn )
  120. {
  121. TraceFunc( "" );
  122. LogMsg( "Entering " __FUNCTION__ "()" );
  123. DWORD dwReturnValue = NO_ERROR;
  124. // Call the base class helper function to perform some registry and service
  125. // related configuration from the INF file.
  126. dwReturnValue = TW32( BaseClass::DwOcCompleteInstallation( pcszInstallSectionNameIn ) );
  127. //
  128. // Register the Generic Script resource type extension for cluster startup notifications
  129. //
  130. if ( dwReturnValue == NO_ERROR )
  131. {
  132. HRESULT hrTemp;
  133. TraceFlow( "Attempting to register the Generic Script resource type extension for cluster startup notifications." );
  134. LogMsg( "Attempting to register the Generic Script resource type extension for cluster startup notifications." );
  135. hrTemp = THR( HrRegisterForStartupNotifications( CLSID_ClusCfgResTypeGenScript ) );
  136. if ( FAILED( hrTemp ) )
  137. {
  138. // This is not a fatal error. So, log it and continue.
  139. TraceFlow1( "Non-fatal error %#x occurred registering the Generic Script resource type extension for cluster startup notifications." , hrTemp );
  140. LogMsg( "Non-fatal error %#x occurred registering the Generic Script resource type extension for cluster startup notifications." , hrTemp );
  141. } // if: we could not register the Generic Script resource type extension for cluster startup notifications
  142. else
  143. {
  144. TraceFlow( "Successfully registered the Generic Script resource type extension for cluster startup notifications." );
  145. LogMsg( "Successfully registered the Generic Script resource type extension for cluster startup notifications." );
  146. } // else: the registration was successful
  147. } // if: the call to the base class function succeeded
  148. //
  149. // Register the Majority Node Set resource type extension for cluster startup notifications
  150. //
  151. if ( dwReturnValue == NO_ERROR )
  152. {
  153. HRESULT hrTemp;
  154. TraceFlow( "Attempting to register the Majority Node Set resource type extension for cluster startup notifications." );
  155. LogMsg( "Attempting to register the Majority Node Set resource type extension for cluster startup notifications." );
  156. hrTemp = THR( HrRegisterForStartupNotifications( CLSID_ClusCfgResTypeMajorityNodeSet ) );
  157. if ( FAILED( hrTemp ) )
  158. {
  159. // This is not a fatal error. So, log it and continue.
  160. TraceFlow1( "Non-fatal error %#x occurred registering the Majority Node Set resource type extension for cluster startup notifications." , hrTemp );
  161. LogMsg( "Non-fatal error %#x occurred registering the Majority Node Set resource type extension for cluster startup notifications." , hrTemp );
  162. } // if: we could not register the Majority Node Set resource type extension for cluster startup notifications
  163. else
  164. {
  165. TraceFlow( "Successfully registered the Majority Node Set resource type extension for cluster startup notifications." );
  166. LogMsg( "Successfully registered the Majority Node Set resource type extension for cluster startup notifications." );
  167. } // else: the registration was successful
  168. } // if: the call to the base class function succeeded
  169. TraceFlow1( "Return Value is %#x.", dwReturnValue );
  170. LogMsg( "Return Value is %#x.", dwReturnValue );
  171. RETURN( dwReturnValue );
  172. } //*** CTaskUpgrade::DwOcCompleteInstallation()
  173. /////////////////////////////////////////////////////////////////////////////
  174. //++
  175. //
  176. // DWORD
  177. // CTaskUpgrade::DwGetClusterServiceDirectory
  178. //
  179. // Description:
  180. // This function returns a pointer to the directory in which the cluster
  181. // service binaries are installed. This memory pointed to by this pointer
  182. // should not be freed by the caller.
  183. //
  184. // Arguments:
  185. // const WCHAR *& rpcszDirNamePtrIn
  186. // Reference to the pointer to install directory. The caller should not
  187. // free this memory.
  188. //
  189. // Return Value:
  190. // NO_ERROR if all went well.
  191. // Other Win32 error codes on failure.
  192. //
  193. //--
  194. /////////////////////////////////////////////////////////////////////////////
  195. DWORD
  196. CTaskUpgrade::DwGetClusterServiceDirectory( const WCHAR *& rpcszDirNamePtrIn )
  197. {
  198. TraceFunc( "" );
  199. LogMsg( "Entering " __FUNCTION__ "()" );
  200. DWORD dwReturnValue = NO_ERROR;
  201. // Check if we have already got the cluster service directory. If we already have,
  202. // then return this value.
  203. while( !m_fClusDirFound )
  204. {
  205. // Instantiate a smart pointer to the QUERY_SERVICE_CONFIG structure.
  206. typedef CSmartGenericPtr< CPtrTrait< QUERY_SERVICE_CONFIG > > SmartServiceConfig;
  207. // Connect to the Service Control Manager
  208. SmartServiceHandle shServiceMgr( OpenSCManager( NULL, NULL, GENERIC_READ ) );
  209. // Some arbitrary value.
  210. DWORD cbServiceConfigBufSize = 256;
  211. // Was the service control manager database opened successfully?
  212. if ( shServiceMgr.HHandle() == NULL )
  213. {
  214. dwReturnValue = TW32( GetLastError() );
  215. TraceFlow1( "Error %#x occurred trying to open a connection to the local service control manager.", dwReturnValue );
  216. LogMsg( "Error %#x occurred trying to open a connection to the local service control manager.", dwReturnValue );
  217. break;
  218. } // if: opening the SCM was unsuccessful
  219. // Open a handle to the Cluster Service.
  220. SmartServiceHandle shService( OpenService( shServiceMgr, L"ClusSvc", GENERIC_READ ) );
  221. // Was the handle to the service opened?
  222. if ( shService.HHandle() == NULL )
  223. {
  224. dwReturnValue = TW32( GetLastError() );
  225. TraceFlow1( "Error %#x occurred trying to open a handle to the cluster service.", dwReturnValue );
  226. LogMsg( "Error %#x occurred trying to open a handle to the cluster service.", dwReturnValue );
  227. break;
  228. } // if: the handle could not be opened
  229. do
  230. {
  231. DWORD cbRequiredSize = 0;
  232. // Allocate memory for the service configuration info buffer. The memory is automatically freed when the
  233. // object is destroyed.
  234. SmartServiceConfig spscServiceConfig( reinterpret_cast< QUERY_SERVICE_CONFIG * >( new BYTE[ cbServiceConfigBufSize ] ) );
  235. // Did the memory allocation succeed
  236. if ( spscServiceConfig.FIsEmpty() )
  237. {
  238. dwReturnValue = TW32( ERROR_NOT_ENOUGH_MEMORY );
  239. TraceFlow( "Error: There was not enough memory to get the cluster service configuration information." );
  240. LogMsg( "Error: There was not enough memory to get the cluster service configuration information." );
  241. break;
  242. } // if: memory allocation failed
  243. // Get the configuration information.
  244. if ( QueryServiceConfig(
  245. shService.HHandle()
  246. , spscServiceConfig.PMem()
  247. , cbServiceConfigBufSize
  248. , &cbRequiredSize
  249. )
  250. == FALSE
  251. )
  252. {
  253. dwReturnValue = GetLastError();
  254. if ( dwReturnValue != ERROR_INSUFFICIENT_BUFFER )
  255. {
  256. TW32( dwReturnValue );
  257. TraceFlow1( "Error %#x occurred trying to get the cluster service configuration information.", dwReturnValue );
  258. LogMsg( "Error %#x occurred trying to get the cluster service configuration information.", dwReturnValue );
  259. break;
  260. } // if: something has really gone wrong
  261. // We need to allocate more memory - try again
  262. dwReturnValue = NO_ERROR;
  263. cbServiceConfigBufSize = cbRequiredSize;
  264. } // if: QueryServiceConfig() failed
  265. else
  266. {
  267. // Find the last backslash character in the service binary path.
  268. WCHAR * pszPathName = spscServiceConfig.PMem()->lpBinaryPathName;
  269. WCHAR * pszLastBackslash = wcsrchr( pszPathName, L'\\' );
  270. if ( pszLastBackslash != NULL )
  271. {
  272. // Terminate the string here.
  273. *pszLastBackslash = L'\0';
  274. } // if: we found the last backslash
  275. // Move the service binary path to the beginning of the buffer.
  276. MoveMemory( spscServiceConfig.PMem(), pszPathName, ( wcslen( pszPathName ) + 1 ) * sizeof( *pszPathName ) );
  277. // Store the pointer to the buffer in the member variable and
  278. // detach this memory from the smart pointer (this will not delete the memory).
  279. m_sszClusterServiceDir.Assign( reinterpret_cast< WCHAR * >( spscServiceConfig.PRelease() ) );
  280. // Indicate the we have successfully found the cluster service directory.
  281. m_fClusDirFound = true;
  282. break;
  283. } // else: QueryServiceConfig() has succeeded
  284. }
  285. while( true ); // while: loop infinitely
  286. // We are done
  287. break;
  288. }
  289. // Initialize the output.
  290. rpcszDirNamePtrIn = m_sszClusterServiceDir.PMem();
  291. LogMsg( "Return Value is %#x.", dwReturnValue );
  292. TraceFlow1( "Return Value is %#x.", dwReturnValue );
  293. RETURN( dwReturnValue );
  294. } //*** CTaskUpgrade::DwGetClusterServiceDirectory()
  295. /////////////////////////////////////////////////////////////////////////////
  296. //++
  297. //
  298. // HRESULT
  299. // CTaskUpgrade::HrRegisterForStartupNotifications
  300. //
  301. // Description:
  302. // This function registers a COM component for receiving cluster startup
  303. // notifications.
  304. //
  305. // Arguments:
  306. // const CLSID & rclsidComponentIn
  307. // Reference to the CLSID of the component that is to receive cluster
  308. // startup notifications.
  309. //
  310. // Return Value:
  311. // S_OK if all went well.
  312. // Other HRESULTS failure.
  313. //
  314. //--
  315. /////////////////////////////////////////////////////////////////////////////
  316. HRESULT
  317. CTaskUpgrade::HrRegisterForStartupNotifications( const CLSID & rclsidComponentIn )
  318. {
  319. TraceFunc( "" );
  320. LogMsg( "Entering " __FUNCTION__ "()" );
  321. HRESULT hr = S_OK;
  322. CoInitializeEx( NULL, COINIT_MULTITHREADED );
  323. do
  324. {
  325. CSmartIfacePtr< ICatRegister > spcrCatReg;
  326. {
  327. ICatRegister * pcrCatReg = NULL;
  328. hr = THR(
  329. CoCreateInstance(
  330. CLSID_StdComponentCategoriesMgr
  331. , NULL
  332. , CLSCTX_INPROC_SERVER
  333. , __uuidof( pcrCatReg )
  334. , reinterpret_cast< void ** >( &pcrCatReg )
  335. )
  336. );
  337. if ( FAILED( hr ) )
  338. {
  339. LogMsg( "Error %#x occurred trying to create the StdComponentCategoriesMgr component.", hr );
  340. TraceFlow1( "Error %#x occurred trying to create the StdComponentCategoriesMgr component.", hr );
  341. break;
  342. } // if: we could not create the StdComponentCategoriesMgr component
  343. // Assign to a smart pointer for automatic release.
  344. spcrCatReg.Attach( pcrCatReg );
  345. }
  346. {
  347. CATID rgCatId[ 1 ];
  348. rgCatId[ 0 ] = CATID_ClusCfgStartupListeners;
  349. hr = THR(
  350. spcrCatReg->RegisterClassImplCategories( rclsidComponentIn, ARRAYSIZE( rgCatId ), rgCatId ) );
  351. if ( FAILED( hr ) )
  352. {
  353. LogMsg( "Error %#x occurred trying to register the component for cluster startup notifications.", hr );
  354. TraceFlow1( "Error %#x occurred during the call to ICatRegister::UnRegisterClassImplCategories().", hr );
  355. break;
  356. } // if: we could not register the component for startup notifications
  357. }
  358. LogMsg( "Successfully registered for startup notifications." );
  359. TraceFlow( "Successfully registered for startup notifications." );
  360. }
  361. while( false ); // dummy do-while loop to avoid gotos
  362. CoUninitialize();
  363. LogMsg( "Return Value is %#x.", hr );
  364. TraceFlow1( "Return Value is %#x.", hr );
  365. HRETURN( hr );
  366. } //*** CTaskUpgrade::HrRegisterForStartupNotifications()