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.

649 lines
20 KiB

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