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.

1025 lines
29 KiB

  1. /////////////////////////////////////////////////////////////////////
  2. //
  3. // SvcEnum.cpp
  4. //
  5. // This file contains routines to enumerate services.
  6. //
  7. // HISTORY
  8. // t-danmo 96.09.13 Creation (split of log.cpp)
  9. // t-danm 96.07.14 Moved member functions Service_* from
  10. // CFileMgmtComponent to CFileMgmtComponentData.
  11. //
  12. /////////////////////////////////////////////////////////////////////
  13. #include "stdafx.h"
  14. #include "cmponent.h"
  15. #include "compdata.h" // QueryComponentDataRef().m_hScManager
  16. #include "safetemp.h"
  17. #include "macros.h"
  18. USE_HANDLE_MACROS("FILEMGMT(SvcEnum.cpp)")
  19. #include "FileSvc.h" // FileServiceProvider
  20. #include "dataobj.h"
  21. #include <comstrm.h>
  22. #ifdef _DEBUG
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. #include "progress.h"
  28. /*
  29. // forward declarations
  30. class CServiceCookieBlock;
  31. /////////////////////////////////////////////////////////////////////
  32. class CServiceCookie : public CFileMgmtResultCookie
  33. {
  34. public:
  35. CString GetServiceDisplaySecurityContext ();
  36. CString GetServiceDisplayStartUpType ();
  37. CString GetServiceDisplayStatus ();
  38. CString GetServiceDescription ();
  39. virtual HRESULT CompareSimilarCookies( CCookie* pOtherCookie, int* pnResult);
  40. CServiceCookie() : CFileMgmtResultCookie( FILEMGMT_SERVICE ) {}
  41. virtual HRESULT GetServiceName( OUT CString& strServiceName );
  42. virtual HRESULT GetServiceDisplayName( OUT CString& strServiceName );
  43. virtual BSTR QueryResultColumnText( int nCol, CFileMgmtComponentData& refcdata );
  44. inline ENUM_SERVICE_STATUS* GetServiceStatus()
  45. {
  46. ASSERT( NULL != m_pobject );
  47. return (ENUM_SERVICE_STATUS*)m_pobject;
  48. }
  49. CString m_strDescription; // Description of service
  50. DWORD m_dwCurrentState;
  51. DWORD m_dwStartType;
  52. CString m_strServiceStartName; // Name of the account which the service process will be logged (eg: ".\\Administrator")
  53. virtual void AddRefCookie();
  54. virtual void ReleaseCookie();
  55. // CHasMachineName
  56. CServiceCookieBlock* m_pCookieBlock;
  57. DECLARE_FORWARDS_MACHINE_NAME(m_pCookieBlock)
  58. };
  59. HRESULT CServiceCookie::GetServiceName(OUT CString& strServiceName )
  60. {
  61. ENUM_SERVICE_STATUS * pESS = (ENUM_SERVICE_STATUS *)m_pobject;
  62. ASSERT( NULL != pESS );
  63. ASSERT( NULL != pESS->lpServiceName );
  64. strServiceName = pESS->lpServiceName;
  65. return S_OK;
  66. }
  67. HRESULT CServiceCookie::GetServiceDisplayName(OUT CString& strServiceDisplayName )
  68. {
  69. ENUM_SERVICE_STATUS * pESS = (ENUM_SERVICE_STATUS *)m_pobject;
  70. ASSERT( NULL != pESS );
  71. ASSERT( NULL != pESS->lpDisplayName );
  72. strServiceDisplayName = pESS->lpDisplayName;
  73. return S_OK;
  74. }
  75. BSTR CServiceCookie::QueryResultColumnText( int nCol, CFileMgmtComponentData& refcdata )
  76. {
  77. switch (nCol)
  78. {
  79. case COLNUM_SERVICES_SERVICENAME:
  80. return GetServiceStatus()->lpDisplayName;
  81. case COLNUM_SERVICES_DESCRIPTION:
  82. return const_cast<BSTR>((LPCTSTR)m_strDescription);
  83. case COLNUM_SERVICES_STATUS:
  84. return const_cast<BSTR>( Service_PszMapStateToName(m_dwCurrentState) );
  85. case COLNUM_SERVICES_STARTUPTYPE:
  86. return const_cast<BSTR>( Service_PszMapStartupTypeToName(m_dwStartType) );
  87. case COLNUM_SERVICES_SECURITYCONTEXT:
  88. return const_cast<BSTR>((LPCTSTR)m_strServiceStartName);
  89. default:
  90. ASSERT(FALSE);
  91. break;
  92. }
  93. return L"";
  94. }
  95. class CServiceCookieBlock : public CCookieBlock<CServiceCookie>,
  96. public CStoresMachineName
  97. {
  98. public:
  99. inline CServiceCookieBlock(
  100. CServiceCookie* aCookies, // use vector ctor, we use vector dtor
  101. INT cCookies,
  102. LPCTSTR lpcszMachineName,
  103. PVOID pvCookieData)
  104. : CCookieBlock<CServiceCookie>( aCookies, cCookies ),
  105. CStoresMachineName( lpcszMachineName ),
  106. m_pvCookieData(pvCookieData)
  107. {
  108. for (int i = 0; i < cCookies; i++)
  109. // {
  110. // aCookies[i].ReadMachineNameFrom( (CHasMachineName*)this );
  111. aCookies[i].m_pCookieBlock = this;
  112. // }
  113. }
  114. virtual ~CServiceCookieBlock();
  115. private:
  116. PVOID m_pvCookieData; // actually ENUM_SERVICE_STATUS*
  117. };
  118. DEFINE_COOKIE_BLOCK(CServiceCookie)
  119. CServiceCookieBlock::~CServiceCookieBlock()
  120. {
  121. if (NULL != m_pvCookieData)
  122. {
  123. delete m_pvCookieData;
  124. m_pvCookieData = NULL;
  125. }
  126. }
  127. void CServiceCookie::AddRefCookie() { m_pCookieBlock->AddRef(); }
  128. void CServiceCookie::ReleaseCookie() { m_pCookieBlock->Release(); }
  129. DEFINE_FORWARDS_MACHINE_NAME( CServiceCookie, m_pCookieBlock )
  130. */
  131. int g_marker;
  132. class CNewServiceCookie
  133. : public CNewResultCookie
  134. {
  135. public:
  136. CNewServiceCookie()
  137. : CNewResultCookie( (PVOID)&g_marker, FILEMGMT_SERVICE )
  138. {}
  139. virtual ~CNewServiceCookie();
  140. virtual BSTR QueryResultColumnText( int nCol, CFileMgmtComponentData& refcdata );
  141. virtual HRESULT CompareSimilarCookies(CCookie * pOtherCookie, int * pnResult);
  142. virtual HRESULT GetServiceName( OUT CString& strServiceName );
  143. virtual HRESULT GetServiceDisplayName( OUT CString& strServiceName );
  144. virtual HRESULT GetExplorerViewDescription( OUT CString& strExplorerViewDescription );
  145. virtual HRESULT SimilarCookieIsSameObject( CNewResultCookie* pOtherCookie, BOOL* pbSame );
  146. virtual BOOL CopySimilarCookie( CNewResultCookie* pcookie );
  147. public:
  148. CString m_strServiceName;
  149. CString m_strDisplayName;
  150. CString m_strDescription;
  151. DWORD m_dwState;
  152. DWORD m_dwStartType;
  153. CString m_strStartName;
  154. }; // CNewServiceCookie
  155. CNewServiceCookie::~CNewServiceCookie()
  156. {
  157. }
  158. BSTR CNewServiceCookie::QueryResultColumnText(
  159. int nCol,
  160. CFileMgmtComponentData& /*refcdata*/ )
  161. {
  162. switch (nCol)
  163. {
  164. case COLNUM_SERVICES_SERVICENAME:
  165. return const_cast<BSTR>((LPCTSTR)m_strDisplayName);
  166. case COLNUM_SERVICES_DESCRIPTION:
  167. return const_cast<BSTR>((LPCTSTR)m_strDescription);
  168. case COLNUM_SERVICES_STATUS:
  169. return const_cast<BSTR>( Service_PszMapStateToName(m_dwState) );
  170. case COLNUM_SERVICES_STARTUPTYPE:
  171. return const_cast<BSTR>( Service_PszMapStartupTypeToName(m_dwStartType) );
  172. case COLNUM_SERVICES_SECURITYCONTEXT:
  173. // JonN 11/14/00 188203 support LocalService/NetworkService
  174. return const_cast<BSTR>(
  175. Service_PszMapStartupAccountToName(m_strStartName) );
  176. default:
  177. ASSERT(FALSE);
  178. break;
  179. }
  180. return L"";
  181. }
  182. HRESULT CNewServiceCookie::CompareSimilarCookies(CCookie * pOtherCookie, int * pnResult)
  183. {
  184. if ( !pOtherCookie || FILEMGMT_SERVICE != QueryObjectType () )
  185. {
  186. ASSERT(FALSE);
  187. return E_FAIL;
  188. }
  189. CNewServiceCookie* pcookie = dynamic_cast <CNewServiceCookie*>(pOtherCookie);
  190. if ( FILEMGMT_SERVICE != pcookie->QueryObjectType ()
  191. || !IsSameType(pcookie) )
  192. {
  193. ASSERT(FALSE);
  194. return E_FAIL;
  195. }
  196. int colNum = *pnResult; // save in case it's overwritten
  197. HRESULT hr = CHasMachineName::CompareMachineNames( *pcookie, pnResult );
  198. if (S_OK != hr || 0 != *pnResult)
  199. return hr;
  200. switch (colNum) // column number
  201. {
  202. case COMPARESIMILARCOOKIE_FULL: // fall through
  203. case COLNUM_SERVICES_SERVICENAME:
  204. *pnResult = lstrcmpi(m_strDisplayName, pcookie->m_strDisplayName);
  205. break;
  206. case COLNUM_SERVICES_DESCRIPTION:
  207. *pnResult = lstrcmpi(m_strDescription, pcookie->m_strDescription);
  208. break;
  209. case COLNUM_SERVICES_STATUS:
  210. {
  211. CString strServiceA = Service_PszMapStateToName(m_dwState);
  212. CString strServiceB = Service_PszMapStateToName(pcookie->m_dwState);
  213. *pnResult = lstrcmpi(strServiceA, strServiceB);
  214. }
  215. break;
  216. case COLNUM_SERVICES_STARTUPTYPE:
  217. {
  218. CString strServiceA = Service_PszMapStartupTypeToName(m_dwStartType);
  219. CString strServiceB = Service_PszMapStartupTypeToName(pcookie->m_dwStartType);
  220. *pnResult = lstrcmpi(strServiceA, strServiceB);
  221. }
  222. break;
  223. case COLNUM_SERVICES_SECURITYCONTEXT:
  224. // JonN 11/14/00 188203 support LocalService/NetworkService
  225. {
  226. CString strServiceA = Service_PszMapStartupAccountToName(m_strStartName);
  227. CString strServiceB = Service_PszMapStartupAccountToName(pcookie->m_strStartName);
  228. *pnResult = lstrcmpi(strServiceA, strServiceB);
  229. }
  230. break;
  231. default:
  232. ASSERT(FALSE);
  233. return E_UNEXPECTED;
  234. }
  235. return S_OK;
  236. }
  237. HRESULT CNewServiceCookie::GetServiceName(OUT CString& strServiceName )
  238. {
  239. strServiceName = m_strServiceName;
  240. return S_OK;
  241. }
  242. HRESULT CNewServiceCookie::GetServiceDisplayName(OUT CString& strServiceDisplayName )
  243. {
  244. strServiceDisplayName = m_strDisplayName;
  245. return S_OK;
  246. }
  247. HRESULT CNewServiceCookie::GetExplorerViewDescription(OUT CString& strExplorerViewDescription )
  248. {
  249. strExplorerViewDescription = m_strDescription;
  250. return S_OK;
  251. }
  252. HRESULT CNewServiceCookie::SimilarCookieIsSameObject(
  253. CNewResultCookie* pOtherCookie,
  254. BOOL* pbSame )
  255. {
  256. if ( !pOtherCookie || !IsSameType(pOtherCookie) )
  257. {
  258. ASSERT(FALSE);
  259. return E_FAIL;
  260. }
  261. int nResult = 0;
  262. HRESULT hr = CHasMachineName::CompareMachineNames( *pOtherCookie, &nResult );
  263. if (S_OK != hr || 0 != nResult)
  264. {
  265. *pbSame = FALSE;
  266. return hr;
  267. }
  268. *pbSame = (0 == lstrcmpi(m_strServiceName,
  269. ((CNewServiceCookie*)pOtherCookie)->m_strServiceName) );
  270. return S_OK;
  271. }
  272. BOOL CNewServiceCookie::CopySimilarCookie( CNewResultCookie* pcookie )
  273. {
  274. if (NULL == pcookie)
  275. {
  276. ASSERT(FALSE);
  277. return FALSE;
  278. }
  279. CNewServiceCookie* pnewcookie = (CNewServiceCookie*)pcookie;
  280. BOOL fChanged = FALSE;
  281. if (m_strServiceName != pnewcookie->m_strServiceName)
  282. {
  283. m_strServiceName = pnewcookie->m_strServiceName;
  284. fChanged = TRUE;
  285. }
  286. if (m_strDisplayName != pnewcookie->m_strDisplayName)
  287. {
  288. m_strDisplayName = pnewcookie->m_strDisplayName;
  289. fChanged = TRUE;
  290. }
  291. if (m_strDescription != pnewcookie->m_strDescription)
  292. {
  293. m_strDescription = pnewcookie->m_strDescription;
  294. fChanged = TRUE;
  295. }
  296. if (m_dwState != pnewcookie->m_dwState)
  297. {
  298. m_dwState = pnewcookie->m_dwState;
  299. fChanged = TRUE;
  300. }
  301. if (m_dwStartType != pnewcookie->m_dwStartType)
  302. {
  303. m_dwStartType = pnewcookie->m_dwStartType;
  304. fChanged = TRUE;
  305. }
  306. if (m_strStartName != pnewcookie->m_strStartName)
  307. {
  308. m_strStartName = pnewcookie->m_strStartName;
  309. fChanged = TRUE;
  310. }
  311. // don't bother with machine name
  312. fChanged |= CNewResultCookie::CopySimilarCookie( pcookie );
  313. return fChanged;
  314. }
  315. /////////////////////////////////////////////////////////////////////
  316. /////////////////////////////////////////////////////////////////////
  317. /////////////////////////////////////////////////////////////////////
  318. // Service_EOpenScManager()
  319. //
  320. // Open the service Service Control Manager database to
  321. // enumerate all available services.
  322. //
  323. // If an error occured, return the error code returned by GetLastError(),
  324. // otherwise return ERROR_SUCCESS.
  325. //
  326. APIERR
  327. CFileMgmtComponentData::Service_EOpenScManager(LPCTSTR pszMachineName)
  328. {
  329. Endorse(pszMachineName == NULL); // TRUE => Local machine
  330. Assert(m_hScManager == NULL && "Service Control Manager should not have been opened yet");
  331. APIERR dwErr = ERROR_SUCCESS;
  332. if (pszMachineName != NULL)
  333. {
  334. if (pszMachineName[0] == _T('\\'))
  335. {
  336. Assert(pszMachineName[1] == _T('\\'));
  337. // Get rid of the \\ at the beginning of machine name
  338. pszMachineName += 2;
  339. }
  340. if (pszMachineName[0] == '\0')
  341. pszMachineName = NULL; // Empty string == Local Machine
  342. }
  343. CWaitCursor wait;
  344. m_hScManager = ::OpenSCManager(
  345. pszMachineName,
  346. NULL,
  347. SC_MANAGER_ENUMERATE_SERVICE);
  348. if (m_hScManager == NULL)
  349. {
  350. dwErr = ::GetLastError();
  351. TRACE3("CFileMgmtComponentData::Service_OpenScManager() - "
  352. _T("Unable to open Service Control Manager database on machine %s. err=%d (0x%X).\n"),
  353. (pszMachineName != NULL) ? pszMachineName : _T("LocalMachine"), dwErr, dwErr);
  354. }
  355. return dwErr;
  356. } // CFileMgmtComponentData::Service_EOpenScManager()
  357. /////////////////////////////////////////////////////////////////////
  358. void
  359. CFileMgmtComponentData::Service_CloseScManager()
  360. {
  361. if (m_hScManager != NULL)
  362. {
  363. CWaitCursor wait; // Auto-wait cursor
  364. (void)::CloseServiceHandle(m_hScManager);
  365. m_hScManager = NULL;
  366. }
  367. } // CFileMgmtComponentData::Service_CloseScManager()
  368. /////////////////////////////////////////////////////////////////////
  369. // CFileMgmtComponentData::Service_PopulateServices()
  370. //
  371. // Enumerate all available services and display them
  372. // into the listview control.
  373. //
  374. // 12/03/98 JonN With the mark-and-sweep change, this no longer adds the items
  375. // the the view
  376. //
  377. HRESULT
  378. CFileMgmtComponentData::Service_PopulateServices(LPRESULTDATA pResultData, CFileMgmtScopeCookie* pcookie)
  379. {
  380. AFX_MANAGE_STATE(AfxGetStaticModuleState( )); // required for CWaitCursor
  381. TEST_NONNULL_PTR_PARAM(pResultData);
  382. TEST_NONNULL_PTR_PARAM(pcookie);
  383. DWORD cbBytesNeeded = 0; // Number of necessary bytes to return all service entries
  384. DWORD dwServicesReturned = 0; // Number of services returned
  385. DWORD dwResumeHandle = 0;
  386. BOOL fRet;
  387. DWORD dwErr = ERROR_SUCCESS;
  388. if (m_hScManager == NULL)
  389. {
  390. dwErr = Service_EOpenScManager(pcookie->QueryTargetServer());
  391. }
  392. if (m_hScManager == NULL)
  393. {
  394. Assert(dwErr != ERROR_SUCCESS);
  395. DoServicesErrMsgBox(::GetActiveWindow(), MB_OK | MB_ICONEXCLAMATION, dwErr,
  396. IDS_MSG_s_UNABLE_TO_OPEN_SERVICE_DATABASE, pcookie->QueryNonNULLMachineName());
  397. return S_OK;
  398. }
  399. //
  400. // The idea here is to ask the enum Api how much memory is
  401. // needed to enumerate all services.
  402. //
  403. {
  404. CWaitCursor wait; // Auto-wait cursor
  405. fRet = ::EnumServicesStatus(
  406. m_hScManager,
  407. SERVICE_WIN32, // Type of services to enumerate
  408. SERVICE_ACTIVE | SERVICE_INACTIVE, // State of services to enumerate
  409. NULL, // Pointer to service status buffer
  410. 0, // Size of service status buffer
  411. OUT &cbBytesNeeded, // Number of necessary bytes to return the remaining service entries
  412. OUT &dwServicesReturned, // Number returned services
  413. OUT &dwResumeHandle); // Pointer to variable for next entry (unused)
  414. }
  415. Report(fRet == FALSE); // First attempt should fail
  416. Report(cbBytesNeeded > 0);
  417. // Add room for 10 extra services (just in case)
  418. cbBytesNeeded += 10 * sizeof(ENUM_SERVICE_STATUS);
  419. // Allocate memory for the enumeration
  420. ENUM_SERVICE_STATUS * prgESS = (ENUM_SERVICE_STATUS *) new BYTE[cbBytesNeeded];
  421. //
  422. // Now call the enum Api to retreive the services
  423. //
  424. {
  425. CWaitCursor wait; // Auto-wait cursor
  426. fRet = ::EnumServicesStatus(
  427. m_hScManager,
  428. SERVICE_WIN32, // Type of services to enumerate
  429. SERVICE_ACTIVE | SERVICE_INACTIVE, // State of services to enumerate
  430. OUT prgESS, // Pointer to service status buffer
  431. IN cbBytesNeeded, // Size of service status buffer
  432. OUT &cbBytesNeeded, // Number of necessary bytes to return the remaining service entries
  433. OUT &dwServicesReturned, // Number of sercvices returned
  434. OUT &dwResumeHandle); // Pointer to variable for next entry
  435. dwErr = ::GetLastError();
  436. }
  437. if (!fRet)
  438. {
  439. Assert(dwErr != ERROR_SUCCESS);
  440. DoServicesErrMsgBox(::GetActiveWindow(), MB_OK | MB_ICONEXCLAMATION, dwErr,
  441. IDS_MSG_s_UNABLE_TO_READ_SERVICES, pcookie->QueryNonNULLMachineName());
  442. delete prgESS;
  443. return S_OK;
  444. }
  445. {
  446. CWaitCursor wait; // Auto-wait cursor
  447. // Add the services to listview
  448. Service_AddServiceItems(pResultData, pcookie, prgESS, dwServicesReturned);
  449. delete prgESS;
  450. }
  451. return S_OK;
  452. } // CFileMgmtComponentData::Service_PopulateServices()
  453. /////////////////////////////////////////////////////////////////////
  454. // CFileMgmtComponentData::Service_AddServiceItems()
  455. //
  456. // Insert service items to the result pane (listview control).
  457. //
  458. // 12/03/98 JonN With the mark-and-sweep change, this no longer adds the items
  459. // the the view
  460. //
  461. HRESULT
  462. CFileMgmtComponentData::Service_AddServiceItems(
  463. LPRESULTDATA /*pResultData*/,
  464. CFileMgmtScopeCookie * pParentCookie,
  465. ENUM_SERVICE_STATUS * prgESS, // IN: Array of structures of services
  466. DWORD nDataItems) // IN: Number of structures in prgESS
  467. {
  468. Assert(pParentCookie != NULL);
  469. Assert(prgESS != NULL);
  470. CString str;
  471. BOOL fResult;
  472. ASSERT(m_hScManager != NULL); // Service control manager should be already opened
  473. for ( ; nDataItems > 0; nDataItems--, prgESS++ )
  474. {
  475. /*
  476. ** Add one line per service
  477. */
  478. // Variables used to query service
  479. SC_HANDLE hService;
  480. union
  481. {
  482. // Service config
  483. QUERY_SERVICE_CONFIG qsc;
  484. BYTE rgbBufferQsc[SERVICE_cbQueryServiceConfigMax];
  485. };
  486. ::ZeroMemory(&qsc, max(sizeof(qsc), sizeof(rgbBufferQsc)));
  487. union
  488. {
  489. // Service description
  490. SERVICE_DESCRIPTION sd;
  491. BYTE rgbBufferSd[SERVICE_cchDescriptionMax * sizeof(TCHAR) + 16];
  492. };
  493. ::ZeroMemory(&sd, max(sizeof(sd), sizeof(rgbBufferSd)));
  494. DWORD cbBytesNeeded;
  495. // Open service to get its configuration
  496. hService = ::OpenService(
  497. m_hScManager,
  498. prgESS->lpServiceName,
  499. SERVICE_QUERY_CONFIG);
  500. if (hService == NULL)
  501. {
  502. TRACE2("Failed to open service %s. err=%u.\n",
  503. prgESS->lpServiceName, ::GetLastError());
  504. }
  505. // Query service config
  506. // This might fail e.g. if insufficient permissions
  507. BOOL fQSCResult = FALSE;
  508. if (NULL != hService)
  509. {
  510. cbBytesNeeded = 0;
  511. fQSCResult = ::QueryServiceConfig(
  512. hService,
  513. OUT &qsc,
  514. sizeof(rgbBufferQsc),
  515. OUT &cbBytesNeeded);
  516. Report(cbBytesNeeded < sizeof(rgbBufferQsc));
  517. }
  518. // Query config description
  519. sd.lpDescription = NULL; // Set the description to empty
  520. if (m_fQueryServiceConfig2 && NULL != hService)
  521. {
  522. // We only call this API if it is supported by target machine
  523. fResult = ::MyQueryServiceConfig2(
  524. &m_fQueryServiceConfig2,
  525. hService,
  526. SERVICE_CONFIG_DESCRIPTION,
  527. OUT rgbBufferSd, // Description of service
  528. sizeof(rgbBufferSd),
  529. OUT &cbBytesNeeded);
  530. if (!fResult)
  531. {
  532. if (!m_fQueryServiceConfig2)
  533. {
  534. // the local machine does not support QueryServiceConfig2
  535. // CODEWORK How could we get here anyhow? JonN 1/31/97
  536. }
  537. else
  538. {
  539. // This is probably because the target machine is running
  540. // an older version of NT not supporting this API.
  541. DWORD dwErr = ::GetLastError();
  542. TRACE2("QueryServiceConfig2(%s) failed. err=%u.\n",
  543. prgESS->lpServiceName, dwErr);
  544. TRACE1("INFO: Machine %s does not support QueryServiceConfig2() API.\n",
  545. pParentCookie->QueryTargetServer() ? pParentCookie->QueryTargetServer() : _T("(Local)"));
  546. Report(dwErr == RPC_S_PROCNUM_OUT_OF_RANGE &&
  547. "Unusual Situation: Expected error should be RPC_S_PROCNUM_OUT_OF_RANGE");
  548. Report(m_fQueryServiceConfig2 != FALSE && "How can this happen???");
  549. m_fQueryServiceConfig2 = FALSE;
  550. }
  551. }
  552. else
  553. {
  554. Assert(cbBytesNeeded < sizeof(rgbBufferSd));
  555. }
  556. } // if
  557. // We limit the length of the service description to 1000 characters
  558. // otherwise mmc.exe will AV.
  559. // CODEWORK remove this when the bug is fixed in MMC
  560. if (NULL != sd.lpDescription)
  561. {
  562. #ifdef _DEBUG
  563. if (lstrlen(sd.lpDescription) >= 1000)
  564. {
  565. TRACE1("INFO: Description of service %s is too long. Only the first 1000 characters will be displayed.\n", prgESS->lpServiceName);
  566. }
  567. #endif
  568. Assert(rgbBufferSd < (BYTE *)sd.lpDescription);
  569. Assert((BYTE *)&sd.lpDescription[1000] < rgbBufferSd + sizeof(rgbBufferSd));
  570. Assert(1000 * sizeof(TCHAR) < sizeof(rgbBufferSd));
  571. sd.lpDescription[1000] = _T('\0');
  572. } // if
  573. // Add the first column
  574. CNewServiceCookie * pnewcookie = new CNewServiceCookie;
  575. pnewcookie->m_strServiceName = prgESS->lpServiceName;
  576. pnewcookie->m_strDisplayName = prgESS->lpDisplayName;
  577. pnewcookie->m_strDescription = sd.lpDescription;
  578. pnewcookie->m_dwState = prgESS->ServiceStatus.dwCurrentState;
  579. pnewcookie->m_dwStartType =
  580. ((!fQSCResult) ? (DWORD)-1 : qsc.dwStartType);
  581. // JonN 4/11/00 17756: The description of "Account Run under" is unlocalized.
  582. // Display empty string instead of "LocalSystem"
  583. pnewcookie->m_strStartName =
  584. ((!fQSCResult || !lstrcmpi(L"LocalSystem",qsc.lpServiceStartName))
  585. ? NULL : qsc.lpServiceStartName);
  586. pnewcookie->SetMachineName( pParentCookie->QueryTargetServer() );
  587. pParentCookie->ScanAndAddResultCookie( pnewcookie );
  588. if (NULL != hService)
  589. {
  590. VERIFY(::CloseServiceHandle(hService));
  591. }
  592. } // for
  593. return S_OK;
  594. } // CFileMgmtComponentData::Service_AddServiceItems()
  595. /////////////////////////////////////////////////////////////////////
  596. // CFileMgmtComponentData::Service_FGetServiceInfoFromIDataObject()
  597. //
  598. // Extract 'machine name', 'service name' and/or 'service display name'
  599. // from the data object.
  600. //
  601. // Return FALSE if data could not be retrived, otherwise return TRUE.
  602. //
  603. BOOL
  604. CFileMgmtComponentData::Service_FGetServiceInfoFromIDataObject(
  605. IDataObject * pDataObject, // IN: Data object
  606. CString * pstrMachineName, // OUT: OPTIONAL: Machine name
  607. CString * pstrServiceName, // OUT: OPTIONAL: Service name
  608. CString * pstrServiceDisplayName) // OUT: OPTIONAL: Service display name
  609. {
  610. Assert(pDataObject != NULL);
  611. Endorse(pstrMachineName == NULL);
  612. Endorse(pstrServiceName == NULL);
  613. Endorse(pstrServiceDisplayName == NULL);
  614. HRESULT hr;
  615. BOOL fSuccess = TRUE;
  616. if (pstrMachineName != NULL)
  617. {
  618. // Get the machine name (computer name) from IDataObject
  619. hr = ::ExtractString(
  620. pDataObject,
  621. CFileMgmtDataObject::m_CFMachineName,
  622. OUT pstrMachineName,
  623. 255);
  624. if (FAILED(hr))
  625. {
  626. TRACE0("CFileMgmtComponentData::Service_FGetServiceInfoFromIDataObject() - Failed to get machine name.\n");
  627. fSuccess = FALSE;
  628. }
  629. } // if
  630. if (pstrServiceName != NULL)
  631. {
  632. // Get the service name from IDataObject
  633. hr = ::ExtractString(
  634. pDataObject,
  635. CFileMgmtDataObject::m_CFServiceName,
  636. OUT pstrServiceName,
  637. 255);
  638. if (FAILED(hr) || pstrServiceName->IsEmpty())
  639. {
  640. TRACE0("CFileMgmtComponentData::Service_FGetServiceInfoFromIDataObject() - Failed to get service name.\n");
  641. fSuccess = FALSE;
  642. }
  643. } // if
  644. if (pstrServiceDisplayName != NULL)
  645. {
  646. // Get the service display name from IDataObject
  647. hr = ::ExtractString(
  648. pDataObject,
  649. CFileMgmtDataObject::m_CFServiceDisplayName,
  650. OUT pstrServiceDisplayName,
  651. 255);
  652. if (FAILED(hr) || pstrServiceDisplayName->IsEmpty())
  653. {
  654. TRACE0("CFileMgmtComponentData::Service_FGetServiceInfoFromIDataObject() - Failed to get service display name\n");
  655. fSuccess = FALSE;
  656. }
  657. } // if
  658. return fSuccess;
  659. } // CFileMgmtComponentData::Service_FGetServiceInfoFromIDataObject()
  660. /////////////////////////////////////////////////////////////////////
  661. // CFileMgmtComponentData::Service_FAddMenuItems()
  662. //
  663. // Add menuitems to the service context menu.
  664. // The same routine will be used to extend context menus of
  665. // others snapins who wants to have "Start", "Stop", "Pause",
  666. // "Resume" and "Restart" menuitems.
  667. //
  668. // Return TRUE if successful, otherwise FALSE.
  669. //
  670. BOOL
  671. CFileMgmtComponentData::Service_FAddMenuItems(
  672. IContextMenuCallback * pContextMenuCallback, // OUT: Object to append menuitems
  673. IDataObject * pDataObject, // IN: Data object
  674. BOOL fIs3rdPartyContextMenuExtension) // IN: TRUE => Add the menu items as a 3rd party extension
  675. {
  676. AFX_MANAGE_STATE(AfxGetStaticModuleState( )); // required for CWaitCursor
  677. Assert(pContextMenuCallback != NULL);
  678. Assert(pDataObject != NULL);
  679. Endorse(m_hScManager == NULL); // TRUE => Network connection was broken
  680. CString strMachineName;
  681. CString strServiceName;
  682. CString strServiceDisplayName;
  683. BOOL fSuccess = TRUE;
  684. if (!Service_FGetServiceInfoFromIDataObject(
  685. pDataObject,
  686. OUT &strMachineName,
  687. OUT &strServiceName,
  688. OUT &strServiceDisplayName))
  689. {
  690. TRACE0("CFileMgmtComponentData::Service_FAddMenuItems() - Unable to query IDataObject for correct clipboard format.\n");
  691. return FALSE;
  692. }
  693. if (fIs3rdPartyContextMenuExtension)
  694. {
  695. Assert(m_hScManager == NULL);
  696. if (m_hScManager == NULL)
  697. (void)Service_EOpenScManager(strMachineName);
  698. }
  699. BOOL rgfMenuFlags[iServiceActionMax];
  700. {
  701. //
  702. // Get the menu flags
  703. //
  704. CWaitCursor wait;
  705. if (!Service_FGetServiceButtonStatus(
  706. m_hScManager,
  707. strServiceName,
  708. OUT rgfMenuFlags,
  709. NULL, // pdwCurrentState
  710. TRUE)) // fSilentError
  711. {
  712. // Nothing to do here
  713. }
  714. }
  715. if (strMachineName.IsEmpty())
  716. strMachineName = g_strLocalMachine;
  717. if (strServiceDisplayName.IsEmpty())
  718. strServiceDisplayName = g_strUnknown;
  719. CString strMenuItem;
  720. CString strStatusBar;
  721. CComQIPtr<IContextMenuCallback2, &IID_IContextMenuCallback2>
  722. spContextMenuCallback2 = pContextMenuCallback;
  723. // Add the menu items
  724. for (INT i = iServiceActionStart; i < iServiceActionMax; i++)
  725. {
  726. LoadStringWithInsertions(IDS_SVC_MENU_SERVICE_START + i, OUT &strMenuItem);
  727. LoadStringWithInsertions(IDS_SVC_STATUSBAR_ss_SERVICE_START + i,
  728. OUT &strStatusBar,
  729. (LPCTSTR)strServiceDisplayName,
  730. (LPCTSTR)strMachineName);
  731. CONTEXTMENUITEM2 contextmenuitem;
  732. ::ZeroMemory(OUT &contextmenuitem, sizeof(contextmenuitem));
  733. USES_CONVERSION;
  734. contextmenuitem.strName = T2OLE(const_cast<LPTSTR>((LPCTSTR)strMenuItem));
  735. contextmenuitem.strStatusBarText = T2OLE(const_cast<LPTSTR>((LPCTSTR)strStatusBar));
  736. contextmenuitem.lCommandID = cmServiceStart + i;
  737. contextmenuitem.lInsertionPointID = fIs3rdPartyContextMenuExtension ? CCM_INSERTIONPOINTID_3RDPARTY_TASK : CCM_INSERTIONPOINTID_PRIMARY_TOP;
  738. contextmenuitem.fFlags = rgfMenuFlags[i] ? MF_ENABLED : MF_GRAYED;
  739. // JonN 4/18/00 Explorer View requires Callback2
  740. static LPTSTR astrLanguageIndependentMenuNames[iServiceActionMax] =
  741. { _T("Start"),
  742. _T("Stop"),
  743. _T("Pause"),
  744. _T("Resume"),
  745. _T("Restart")
  746. };
  747. contextmenuitem.strLanguageIndependentName =
  748. astrLanguageIndependentMenuNames[i];
  749. HRESULT hr = S_OK;
  750. if (spContextMenuCallback2)
  751. hr = spContextMenuCallback2->AddItem( &contextmenuitem );
  752. else
  753. hr = pContextMenuCallback->AddItem( (CONTEXTMENUITEM*)(&contextmenuitem) );
  754. ASSERT( SUCCEEDED(hr) && "Unable to add menu item" );
  755. if ( !fIs3rdPartyContextMenuExtension )
  756. {
  757. contextmenuitem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TASK;
  758. if (spContextMenuCallback2)
  759. hr = spContextMenuCallback2->AddItem( &contextmenuitem );
  760. else
  761. hr = pContextMenuCallback->AddItem( (CONTEXTMENUITEM*)(&contextmenuitem) );
  762. ASSERT( SUCCEEDED(hr) && "Unable to add menu item" );
  763. }
  764. } // for
  765. return fSuccess;
  766. } // CFileMgmtComponentData::Service_FAddMenuItems()
  767. /////////////////////////////////////////////////////////////////////
  768. // CFileMgmtComponentData::Service_FDispatchMenuCommand()
  769. //
  770. // Dispatch a menu command for a given service
  771. //
  772. // Return TRUE if result pane need to be updated, otherwise FALSE.
  773. //
  774. // We might get a cmStart command on a paused service, if the command
  775. // came from the toolbar. For that matter, we might get a command
  776. // on a non-service, until we fix the toolbar button updating.
  777. //
  778. BOOL
  779. CFileMgmtComponentData::Service_FDispatchMenuCommand(
  780. INT nCommandId,
  781. IDataObject * pDataObject)
  782. {
  783. Assert(pDataObject != NULL);
  784. Endorse(m_hScManager == NULL);
  785. CString strMachineName;
  786. CString strServiceName;
  787. CString strServiceDisplayName;
  788. DWORD dwLastError;
  789. if (!Service_FGetServiceInfoFromIDataObject(
  790. pDataObject,
  791. OUT &strMachineName,
  792. OUT &strServiceName,
  793. OUT &strServiceDisplayName))
  794. {
  795. TRACE0("CFileMgmtComponentData::Service_FDispatchMenuCommand() - Unable to read data from IDataObject.\n");
  796. return FALSE;
  797. }
  798. if (m_hScManager == NULL)
  799. {
  800. TRACE0("CFileMgmtComponentData::Service_FDispatchMenuCommand() - Handle m_hScManager is NULL.\n");
  801. return FALSE;
  802. }
  803. if (nCommandId == cmServiceStart || nCommandId == cmServiceStartTask )
  804. {
  805. dwLastError = CServiceControlProgress::S_EStartService(
  806. ::GetActiveWindow(),
  807. m_hScManager,
  808. strMachineName,
  809. strServiceName,
  810. strServiceDisplayName,
  811. 0,
  812. NULL); // no startup parameters passed from menu command
  813. }
  814. else
  815. {
  816. DWORD dwControlCode;
  817. switch (nCommandId)
  818. {
  819. default:
  820. Assert(FALSE); // fall through
  821. case cmServiceStop:
  822. case cmServiceStopTask:
  823. dwControlCode = SERVICE_CONTROL_STOP;
  824. break;
  825. case cmServicePause:
  826. case cmServicePauseTask:
  827. dwControlCode = SERVICE_CONTROL_PAUSE;
  828. break;
  829. case cmServiceResume:
  830. case cmServiceResumeTask:
  831. dwControlCode = SERVICE_CONTROL_CONTINUE;
  832. break;
  833. case cmServiceRestart:
  834. case cmServiceRestartTask:
  835. dwControlCode = SERVICE_CONTROL_RESTART;
  836. break;
  837. } // switch
  838. dwLastError = CServiceControlProgress::S_EControlService(
  839. ::GetActiveWindow(),
  840. m_hScManager,
  841. strMachineName,
  842. strServiceName,
  843. strServiceDisplayName,
  844. dwControlCode);
  845. } // if...else
  846. // We do want to to keep the connection opened
  847. return (dwLastError != CServiceControlProgress::errUserCancelStopDependentServices);
  848. } // CFileMgmtComponentData::Service_FDispatchMenuCommand()
  849. /////////////////////////////////////////////////////////////////////
  850. // CFileMgmtComponentData::Service_FInsertPropertyPages()
  851. //
  852. // Insert property pages of the data object (service).
  853. //
  854. // Return TRUE if successful, otherwise FALSE.
  855. //
  856. // IMPLEMENTATION NOTES
  857. // The routine allocates a CServicePropertyData object which
  858. // is auto-deleted by the property sheet. The property sheet will
  859. // delete the CServicePropertyData object on its WM_DESTROY message.
  860. //
  861. BOOL
  862. CFileMgmtComponentData::Service_FInsertPropertyPages(
  863. LPPROPERTYSHEETCALLBACK pCallBack, // OUT: Object to append property pages
  864. IDataObject * pDataObject, // IN: Data object
  865. LONG_PTR lNotifyHandle) // IN: Handle to notify the parent
  866. {
  867. Assert(pCallBack != NULL);
  868. Assert(pDataObject != NULL);
  869. Endorse(m_hScManager != NULL);
  870. if (m_hScManager == NULL)
  871. {
  872. // Typically because network connection was broken
  873. TRACE0("INFO: m_hScManager is NULL.\n");
  874. return FALSE;
  875. }
  876. CString strMachineName;
  877. CString strServiceName;
  878. CString strServiceDisplayName;
  879. if (!Service_FGetServiceInfoFromIDataObject(
  880. pDataObject,
  881. OUT &strMachineName,
  882. OUT &strServiceName,
  883. OUT &strServiceDisplayName))
  884. {
  885. Assert(FALSE);
  886. return FALSE;
  887. }
  888. CServicePropertyData * pSPD = new CServicePropertyData;
  889. if (!pSPD->FInit(
  890. pDataObject,
  891. strMachineName,
  892. strServiceName,
  893. strServiceDisplayName,
  894. lNotifyHandle))
  895. {
  896. TRACE1("Failure to query service %s.\n", (LPCTSTR)strServiceName);
  897. delete pSPD;
  898. return FALSE;
  899. }
  900. return pSPD->CreatePropertyPages(pCallBack);
  901. } // CFileMgmtComponentData::Service_FInsertPropertyPages()
  902. #ifdef SNAPIN_PROTOTYPER
  903. #include "protyper.cpp"
  904. #endif