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.

446 lines
16 KiB

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