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.

643 lines
19 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // CASvc.cpp
  7. //
  8. // Description:
  9. // Implementation of helper functions for accessing and controlling
  10. // services.
  11. //
  12. // Maintained By:
  13. // David Potter (davidp) December 23, 1996
  14. //
  15. // Revision History:
  16. //
  17. // Notes:
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include <winsvc.h>
  22. #include "resource.h"
  23. #define _RESOURCE_H_
  24. #include "CASvc.h"
  25. #include "ConstDef.h"
  26. #include "ExcOper.h"
  27. #include "TraceTag.h"
  28. #include "CluAdmin.h"
  29. #include <FileMgmt.h>
  30. #ifdef _DEBUG
  31. #define new DEBUG_NEW
  32. #undef THIS_FILE
  33. static char THIS_FILE[] = __FILE__;
  34. #endif
  35. /////////////////////////////////////////////////////////////////////////////
  36. // Global Variables
  37. /////////////////////////////////////////////////////////////////////////////
  38. #ifdef _DEBUG
  39. CTraceTag g_tagService( _T("Service"), _T("SERVICE"), 0 );
  40. #endif
  41. /////////////////////////////////////////////////////////////////////////////
  42. //++
  43. //
  44. // HOpenCluster
  45. //
  46. // Description:
  47. // Open a cluster. If it fails, ask if the cluster service should be
  48. // started.
  49. //
  50. // Arguments:
  51. // pszClusterIn -- Name of cluster.
  52. //
  53. // Return Values:
  54. // hCluster -- Cluster handle or NULL.
  55. //
  56. //--
  57. /////////////////////////////////////////////////////////////////////////////
  58. HCLUSTER
  59. HOpenCluster(
  60. IN LPCTSTR pszClusterIn
  61. )
  62. {
  63. HCLUSTER hCluster = NULL;
  64. HRESULT hr;
  65. DWORD dwStatus;
  66. DWORD dwClusterState;
  67. LPTSTR pszRealCluster;
  68. TCHAR szRealClusterName[ MAX_PATH ];
  69. CString strMsg;
  70. CFrameWnd * pframeMain;
  71. ASSERT( pszClusterIn != NULL );
  72. pframeMain = PframeMain();
  73. ASSERT( pframeMain != NULL );
  74. if ( _tcscmp( pszClusterIn, _T(".") ) == 0 )
  75. {
  76. DWORD nSize = sizeof( szRealClusterName ) / sizeof( TCHAR );
  77. pszRealCluster = NULL;
  78. GetComputerName( szRealClusterName, &nSize );
  79. } // if: connecting to the local machine
  80. else
  81. {
  82. pszRealCluster = (LPTSTR) pszClusterIn;
  83. _tcscpy( szRealClusterName, pszClusterIn );
  84. } // else: not connecting to the local machine
  85. // Display a message on the status bar.
  86. {
  87. CString strStatusBarText;
  88. strStatusBarText.FormatMessage( IDS_SB_OPENING_CONNECTION, szRealClusterName );
  89. pframeMain->SetMessageText( strStatusBarText );
  90. pframeMain->UpdateWindow();
  91. } // Display a message on the status bar
  92. // Encapsulate wait cursor class.
  93. {
  94. CWaitCursor wc;
  95. Trace( g_tagService, _T("HOpenCluster() - Getting node cluster state on '%s'"), szRealClusterName );
  96. // Get the cluster state of the node.
  97. dwStatus = GetNodeClusterState( pszRealCluster, &dwClusterState );
  98. if ( dwStatus != ERROR_SUCCESS )
  99. {
  100. CNTException nte( dwStatus, IDS_CANNOT_START_CLUSTER_SERVICE, szRealClusterName, NULL, FALSE /*bAutoDelete*/ );
  101. nte.ReportError( MB_OK | MB_ICONSTOP );
  102. goto Cleanup;
  103. }
  104. Trace( g_tagService, _T("HOpenCluster() - Node cluster state on '%s' is 0x%08.8x"), szRealClusterName, dwClusterState );
  105. } // Encapsulate wait cursor class
  106. // Check to see make sure that clustering is installed and configured
  107. // on the specified node.
  108. if ( ( dwClusterState == ClusterStateNotInstalled )
  109. || ( dwClusterState == ClusterStateNotConfigured ) )
  110. {
  111. strMsg.FormatMessage( IDS_CANNOT_START_CLUSTER_SERVICE, szRealClusterName );
  112. AfxMessageBox( strMsg, MB_OK | MB_ICONSTOP );
  113. goto Cleanup;
  114. } // if: clustering not installed or configured
  115. // If the cluster service is not running, ask if it should be started.
  116. if ( dwClusterState == ClusterStateNotRunning )
  117. {
  118. ID id;
  119. // Ask the user if the cluster service should be started.
  120. strMsg.FormatMessage( IDS_START_CLUSTER_SERVICE, szRealClusterName );
  121. id = AfxMessageBox( strMsg, MB_YESNO | MB_ICONEXCLAMATION );
  122. if ( id == IDYES )
  123. {
  124. // Display a message on the status bar.
  125. {
  126. CString strStatusBarText;
  127. strStatusBarText.FormatMessage( IDS_SB_STARTING_CLUSTER_SERVICE, szRealClusterName );
  128. pframeMain->SetMessageText( strStatusBarText );
  129. pframeMain->UpdateWindow();
  130. } // Display a message on the status bar
  131. // Encapsulate wait cursor class.
  132. {
  133. CWaitCursor wc;
  134. // Start the service.
  135. hr = HrStartService( CLUSTER_SERVICE_NAME, szRealClusterName );
  136. if ( ! FAILED( hr ) && ( hr != S_FALSE ) )
  137. {
  138. if ( hr == S_OK )
  139. {
  140. // Wait a second. This is required to make sure that the
  141. // cluster service is running and ready to receive RPC
  142. // connections.
  143. Sleep( 1000 );
  144. } // if: user didn't cancel the start operation
  145. } // if: service started successfully
  146. else
  147. {
  148. CNTException nte( hr, IDS_CANNOT_START_CLUSTER_SERVICE, szRealClusterName, NULL, FALSE /*bAutoDelete*/ );
  149. nte.ReportError();
  150. goto Cleanup;
  151. } // else: failed to start the service
  152. } // Encapsulate wait cursor class
  153. } // if: user approved starting the service
  154. } // if: cluster service not running
  155. // Encapsulate wait cursor class.
  156. {
  157. CWaitCursor wc;
  158. // Display a message on the status bar.
  159. {
  160. CString strStatusBarText;
  161. strStatusBarText.FormatMessage( IDS_SB_OPENING_CONNECTION, szRealClusterName );
  162. pframeMain->SetMessageText( strStatusBarText );
  163. pframeMain->UpdateWindow();
  164. } // Display a message on the status bar
  165. Trace( g_tagService, _T("HOpenCluster() - Opening the cluster on '%s'"), szRealClusterName );
  166. // Open the cluster.
  167. hCluster = OpenCluster( pszRealCluster );
  168. if ( hCluster == NULL )
  169. {
  170. CNTException nte( GetLastError(), IDS_OPEN_NODE_ERROR, szRealClusterName, NULL, FALSE /*bAutoDelete*/ );
  171. dwStatus = nte.Sc();
  172. nte.ReportError();
  173. goto Cleanup;
  174. } // if: error opening the cluster
  175. } // Encapsulate wait cursor class
  176. Cleanup:
  177. // Reset the message on the status bar.
  178. pframeMain->SetMessageText( AFX_IDS_IDLEMESSAGE );
  179. pframeMain->UpdateWindow();
  180. if ( dwStatus != ERROR_SUCCESS )
  181. {
  182. SetLastError( dwStatus );
  183. } // if: error occurred
  184. return hCluster;
  185. } //*** HOpenCluster()
  186. /////////////////////////////////////////////////////////////////////////////
  187. //++
  188. //
  189. // BCanServiceBeStarted
  190. //
  191. // Description:
  192. // Find out if a service can be started on a specified node or not.
  193. //
  194. // Arguments:
  195. // pszServiceNameIn -- Name of service.
  196. // pszNodeIn -- Name of node.
  197. //
  198. // Return Values:
  199. // TRUE -- Service can be started on the specified node.
  200. // FALSE -- Service can not be started on the specified node.
  201. //
  202. //--
  203. /////////////////////////////////////////////////////////////////////////////
  204. BOOL
  205. BCanServiceBeStarted(
  206. LPCTSTR pszServiceNameIn,
  207. LPCTSTR pszNodeIn
  208. )
  209. {
  210. BOOL bCanBeStarted = FALSE;
  211. DWORD dwStatus = ERROR_SUCCESS;
  212. SC_HANDLE hSCManager = NULL;
  213. SC_HANDLE hService = NULL;
  214. SERVICE_STATUS ssServiceStatus;
  215. // Open the Service Control Manager.
  216. hSCManager = OpenSCManager( pszNodeIn, NULL /*lpDatabaseName*/, GENERIC_READ );
  217. if ( hSCManager == NULL )
  218. {
  219. dwStatus = GetLastError();
  220. Trace( g_tagService, _T("BCanServiceBeStarted() - Cannot access service control manager on node '%s'! Error: %u."), pszNodeIn, dwStatus );
  221. goto Cleanup;
  222. } // if: error opening the Service Control Manager
  223. // Open the service.
  224. hService = OpenService( hSCManager, pszServiceNameIn, SERVICE_ALL_ACCESS );
  225. if ( hService == NULL )
  226. {
  227. dwStatus = GetLastError();
  228. Trace( g_tagService, _T("BCanServiceBeStarted() - Cannot open service %s. Error: %u."), pszServiceNameIn, dwStatus );
  229. if ( dwStatus != ERROR_SERVICE_DOES_NOT_EXIST )
  230. {
  231. bCanBeStarted = TRUE;
  232. } // if: error not Service Does Not Exist
  233. goto Cleanup;
  234. } // if: error opening the service
  235. // Query the service status.
  236. if ( QueryServiceStatus( hService, &ssServiceStatus ) )
  237. {
  238. if ( ssServiceStatus.dwCurrentState == SERVICE_STOPPED )
  239. {
  240. bCanBeStarted = TRUE;
  241. } // if: service is stopped
  242. } // if: service status queried successfully
  243. else
  244. {
  245. dwStatus = GetLastError();
  246. } // if: error querying service status
  247. Cleanup:
  248. if ( hService != NULL )
  249. {
  250. CloseServiceHandle( hService );
  251. }
  252. if ( hSCManager != NULL )
  253. {
  254. CloseServiceHandle( hSCManager );
  255. }
  256. SetLastError( dwStatus );
  257. return bCanBeStarted;
  258. } //*** BCanServiceBeStarted()
  259. /////////////////////////////////////////////////////////////////////////////
  260. //++
  261. //
  262. // BIsServiceInstalled
  263. //
  264. // Routine Description:
  265. // Find out if a service is installed on a specified node or not.
  266. //
  267. // Arguments:
  268. // pszServiceNameIn -- Name of service.
  269. // pszNodeIn -- Name of node.
  270. //
  271. // Return Value:
  272. // TRUE -- Service is running on the specified node.
  273. // FALSE -- Service is not running on the specified node.
  274. //
  275. //--
  276. /////////////////////////////////////////////////////////////////////////////
  277. BOOL
  278. BIsServiceInstalled(
  279. LPCTSTR pszServiceNameIn,
  280. LPCTSTR pszNodeIn
  281. )
  282. {
  283. BOOL bInstalled = FALSE;
  284. DWORD dwStatus = ERROR_SUCCESS;
  285. SC_HANDLE hSCManager = NULL;
  286. SC_HANDLE hService = NULL;
  287. // Open the Service Control Manager.
  288. hSCManager = OpenSCManager( pszNodeIn, NULL /*lpDatabaseName*/, GENERIC_READ );
  289. if ( hSCManager == NULL )
  290. {
  291. dwStatus = GetLastError();
  292. Trace( g_tagService, _T("BIsServiceInstalled() - Cannot access service control manager on node '%s'! Error: %u."), pszNodeIn, dwStatus );
  293. goto Cleanup;
  294. } // if: error opening the Service Control Manager
  295. // Open the service.
  296. hService = OpenService( hSCManager, pszServiceNameIn, SERVICE_ALL_ACCESS );
  297. if ( hService == NULL )
  298. {
  299. dwStatus = GetLastError();
  300. Trace( g_tagService, _T("BIsServiceInstalled() - Cannot open service %s. Error: %u."), pszServiceNameIn, dwStatus );
  301. if ( dwStatus != ERROR_SERVICE_DOES_NOT_EXIST )
  302. {
  303. bInstalled = TRUE;
  304. } // if: error not Service Does Not Exist
  305. } // if: error opening the service
  306. else
  307. {
  308. bInstalled = TRUE;
  309. } // else: service opened successfully
  310. Cleanup:
  311. if ( hService != NULL )
  312. {
  313. CloseServiceHandle( hService );
  314. }
  315. if ( hSCManager != NULL )
  316. {
  317. CloseServiceHandle( hSCManager );
  318. }
  319. SetLastError( dwStatus );
  320. return bInstalled;
  321. } //*** BIsServiceInstalled()
  322. /////////////////////////////////////////////////////////////////////////////
  323. //++
  324. //
  325. // BIsServiceRunning
  326. //
  327. // Description:
  328. // Find out if a service is running on a specified node or not.
  329. //
  330. // Arguments:
  331. // pszServiceNameIn -- Name of service.
  332. // pszNodeIn -- Name of node.
  333. //
  334. // Return Values:
  335. // TRUE -- Service is running on the specified node.
  336. // FALSE -- Service is not running on the specified node.
  337. //
  338. //--
  339. /////////////////////////////////////////////////////////////////////////////
  340. BOOL
  341. BIsServiceRunning(
  342. LPCTSTR pszServiceNameIn,
  343. LPCTSTR pszNodeIn
  344. )
  345. {
  346. BOOL bRunning = FALSE;
  347. DWORD dwStatus = ERROR_SUCCESS;
  348. SC_HANDLE hSCManager = NULL;
  349. SC_HANDLE hService = NULL;
  350. SERVICE_STATUS ssServiceStatus;
  351. // Open the Service Control Manager.
  352. hSCManager = OpenSCManager( pszNodeIn, NULL /*lpDatabaseName*/, GENERIC_READ );
  353. if ( hSCManager == NULL )
  354. {
  355. dwStatus = GetLastError();
  356. Trace( g_tagService, _T("BIsServiceRunning() - Cannot access service control manager on node '%s'! Error: %u."), pszNodeIn, dwStatus );
  357. goto Cleanup;
  358. } // if: error opening the Service Control Manager
  359. // Open the service.
  360. hService = OpenService( hSCManager, pszServiceNameIn, SERVICE_ALL_ACCESS );
  361. if ( hService == NULL )
  362. {
  363. dwStatus = GetLastError();
  364. Trace( g_tagService, _T("BIsServiceRunning() - Cannot open service %s. Error: %u."), pszServiceNameIn, dwStatus );
  365. goto Cleanup;
  366. } // if: error opening the service
  367. // Query the service status.
  368. if ( QueryServiceStatus( hService, &ssServiceStatus ) )
  369. {
  370. if ( ssServiceStatus.dwCurrentState == SERVICE_RUNNING )
  371. {
  372. bRunning = TRUE;
  373. } // if: service is running
  374. } // if: service status queried successfully
  375. Cleanup:
  376. if ( hService != NULL )
  377. {
  378. CloseServiceHandle( hService );
  379. }
  380. if ( hSCManager != NULL )
  381. {
  382. CloseServiceHandle( hSCManager );
  383. }
  384. SetLastError( dwStatus );
  385. return bRunning;
  386. } //*** BIsServiceRunning()
  387. /////////////////////////////////////////////////////////////////////////////
  388. //++
  389. //
  390. // HrStartService
  391. //
  392. // Description:
  393. // Start a service on a specified node.
  394. //
  395. // Arguments:
  396. // pszServiceNameIn -- Name of service.
  397. // pszNodeIn -- Name of node.
  398. //
  399. // Return Values:
  400. // S_OK -- Service started successfully.
  401. // Any errors returned by SVCMGMT_IStartStopHelper::StartServiceHelper().
  402. //
  403. //--
  404. /////////////////////////////////////////////////////////////////////////////
  405. HRESULT
  406. HrStartService(
  407. LPCTSTR pszServiceNameIn,
  408. LPCTSTR pszNodeIn
  409. )
  410. {
  411. HRESULT hr = S_OK;
  412. ISvcMgmtStartStopHelper * psmssh = NULL;
  413. BSTR bstrNode = NULL;
  414. BSTR bstrServiceName = NULL;
  415. CFrameWnd * pframeMain;
  416. pframeMain = PframeMain();
  417. ASSERT( pframeMain != NULL );
  418. // Display a message on the status bar.
  419. {
  420. CString strStatusBarText;
  421. strStatusBarText.FormatMessage( IDS_SB_STARTING_SERVICE, pszServiceNameIn, pszNodeIn );
  422. Trace( g_tagService, _T("HrStartService() - Starting the '%s' service on node '%s'."), pszServiceNameIn, pszNodeIn );
  423. pframeMain->SetMessageText( strStatusBarText );
  424. pframeMain->UpdateWindow();
  425. } // Display a message on the status bar
  426. // Make BSTRs for the arguments.
  427. bstrNode = SysAllocString( pszNodeIn );
  428. if ( bstrNode == NULL )
  429. {
  430. hr = E_OUTOFMEMORY;
  431. goto Cleanup;
  432. }
  433. bstrServiceName = SysAllocString( pszServiceNameIn );
  434. if ( bstrServiceName == NULL )
  435. {
  436. hr = E_OUTOFMEMORY;
  437. goto Cleanup;
  438. }
  439. // Create the service management object.
  440. hr = CoCreateInstance(
  441. CLSID_SvcMgmt,
  442. NULL,
  443. CLSCTX_INPROC_SERVER,
  444. __uuidof( ISvcMgmtStartStopHelper ),
  445. reinterpret_cast< void ** >( &psmssh )
  446. );
  447. if ( FAILED( hr ) )
  448. {
  449. Trace( g_tagService, _T("HrStartService() - Error creating IStartStopHelper interface. Error: %u."), hr );
  450. goto Cleanup;
  451. }
  452. // Start the service.
  453. hr = psmssh->StartServiceHelper( AfxGetMainWnd()->m_hWnd, bstrNode, bstrServiceName, 0, NULL );
  454. if ( FAILED( hr ) )
  455. {
  456. Trace( g_tagService, _T("HrStartService() - Error from IStartStopHelper::StartServiceHelper() to start the '%s' service on node '%s'. Error: %u."), pszServiceNameIn, pszNodeIn, hr );
  457. goto Cleanup;
  458. }
  459. Cleanup:
  460. if ( bstrNode != NULL )
  461. {
  462. SysFreeString( bstrNode );
  463. }
  464. if ( bstrServiceName != NULL )
  465. {
  466. SysFreeString( bstrServiceName );
  467. }
  468. if ( psmssh != NULL )
  469. {
  470. psmssh->Release();
  471. }
  472. // Reset the message on the status bar.
  473. pframeMain->SetMessageText( AFX_IDS_IDLEMESSAGE );
  474. pframeMain->UpdateWindow();
  475. return hr;
  476. } //*** HrStartService()
  477. /////////////////////////////////////////////////////////////////////////////
  478. //++
  479. //
  480. // HrStopService
  481. //
  482. // Description:
  483. // Stop a service on a specified node.
  484. //
  485. // Arguments:
  486. // pszServiceNameIn -- Name of service.
  487. // pszNodeIn -- Name of node.
  488. //
  489. // Return Values:
  490. // S_OK -- Service stopped successfully.
  491. // Any errors returned by SVCMGMT_IStartStopHelper::ControlServiceHelper().
  492. //
  493. //--
  494. /////////////////////////////////////////////////////////////////////////////
  495. HRESULT
  496. HrStopService(
  497. LPCTSTR pszServiceNameIn,
  498. LPCTSTR pszNodeIn
  499. )
  500. {
  501. HRESULT hr = S_OK;
  502. ISvcMgmtStartStopHelper * psmssh = NULL;
  503. BSTR bstrNode = NULL;
  504. BSTR bstrServiceName = NULL;
  505. CFrameWnd * pframeMain;
  506. pframeMain = PframeMain();
  507. ASSERT( pframeMain != NULL );
  508. // Display a message on the status bar.
  509. {
  510. CString strStatusBarText;
  511. strStatusBarText.FormatMessage( IDS_SB_STOPPING_SERVICE, pszServiceNameIn, pszNodeIn );
  512. Trace( g_tagService, _T("HrStopService() - Stopping the '%s' service on node '%s'."), pszServiceNameIn, pszNodeIn );
  513. pframeMain->SetMessageText( strStatusBarText );
  514. pframeMain->UpdateWindow();
  515. } // Display a message on the status bar
  516. // Make BSTRs for the arguments.
  517. bstrNode = SysAllocString( pszNodeIn );
  518. if ( bstrNode == NULL )
  519. {
  520. hr = E_OUTOFMEMORY;
  521. goto Cleanup;
  522. }
  523. bstrServiceName = SysAllocString( pszServiceNameIn );
  524. if ( bstrServiceName == NULL )
  525. {
  526. hr = E_OUTOFMEMORY;
  527. goto Cleanup;
  528. }
  529. // Create the service management object.
  530. hr = CoCreateInstance(
  531. CLSID_SvcMgmt,
  532. NULL,
  533. CLSCTX_INPROC_SERVER,
  534. __uuidof( ISvcMgmtStartStopHelper ),
  535. reinterpret_cast< void ** >( &psmssh )
  536. );
  537. if ( FAILED( hr ) )
  538. {
  539. Trace( g_tagService, _T("HrStopService() - Error creating IStartStopHelper interface. Error: %u."), hr );
  540. goto Cleanup;
  541. }
  542. // Start the service.
  543. hr = psmssh->ControlServiceHelper( AfxGetMainWnd()->m_hWnd, bstrNode, bstrServiceName, SERVICE_CONTROL_STOP );
  544. if ( FAILED( hr ) )
  545. {
  546. Trace( g_tagService, _T("HrStopService() - Error from IStartStopHelper::ControlServiceHelper() to stop the '%s' service on node '%s'. Error: %u."), pszServiceNameIn, pszNodeIn, hr );
  547. goto Cleanup;
  548. }
  549. Cleanup:
  550. if ( bstrNode != NULL )
  551. {
  552. SysFreeString( bstrNode );
  553. }
  554. if ( bstrServiceName != NULL )
  555. {
  556. SysFreeString( bstrServiceName );
  557. }
  558. if ( psmssh != NULL )
  559. {
  560. psmssh->Release();
  561. }
  562. // Reset the message on the status bar.
  563. pframeMain->SetMessageText( AFX_IDS_IDLEMESSAGE );
  564. pframeMain->UpdateWindow();
  565. return hr;
  566. } //*** HrStopService()