|
|
/////////////////////////////////////////////////////////////////////
//
// SvcEnum.cpp
//
// This file contains routines to enumerate services.
//
// HISTORY
// t-danmo 96.09.13 Creation (split of log.cpp)
// t-danm 96.07.14 Moved member functions Service_* from
// CFileMgmtComponent to CFileMgmtComponentData.
//
/////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "cmponent.h"
#include "compdata.h" // QueryComponentDataRef().m_hScManager
#include "safetemp.h"
#include "macros.h"
USE_HANDLE_MACROS("FILEMGMT(SvcEnum.cpp)")
#include "FileSvc.h" // FileServiceProvider
#include "dataobj.h"
#include <comstrm.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
#include "progress.h"
/*
// forward declarations
class CServiceCookieBlock;
/////////////////////////////////////////////////////////////////////
class CServiceCookie : public CFileMgmtResultCookie { public: CString GetServiceDisplaySecurityContext (); CString GetServiceDisplayStartUpType (); CString GetServiceDisplayStatus (); CString GetServiceDescription (); virtual HRESULT CompareSimilarCookies( CCookie* pOtherCookie, int* pnResult); CServiceCookie() : CFileMgmtResultCookie( FILEMGMT_SERVICE ) {} virtual HRESULT GetServiceName( OUT CString& strServiceName ); virtual HRESULT GetServiceDisplayName( OUT CString& strServiceName ); virtual BSTR QueryResultColumnText( int nCol, CFileMgmtComponentData& refcdata ); inline ENUM_SERVICE_STATUS* GetServiceStatus() { ASSERT( NULL != m_pobject ); return (ENUM_SERVICE_STATUS*)m_pobject; }
CString m_strDescription; // Description of service
DWORD m_dwCurrentState; DWORD m_dwStartType; CString m_strServiceStartName; // Name of the account which the service process will be logged (eg: ".\\Administrator")
virtual void AddRefCookie(); virtual void ReleaseCookie();
// CHasMachineName
CServiceCookieBlock* m_pCookieBlock; DECLARE_FORWARDS_MACHINE_NAME(m_pCookieBlock) };
HRESULT CServiceCookie::GetServiceName(OUT CString& strServiceName ) { ENUM_SERVICE_STATUS * pESS = (ENUM_SERVICE_STATUS *)m_pobject; ASSERT( NULL != pESS ); ASSERT( NULL != pESS->lpServiceName ); strServiceName = pESS->lpServiceName; return S_OK; }
HRESULT CServiceCookie::GetServiceDisplayName(OUT CString& strServiceDisplayName ) { ENUM_SERVICE_STATUS * pESS = (ENUM_SERVICE_STATUS *)m_pobject; ASSERT( NULL != pESS ); ASSERT( NULL != pESS->lpDisplayName ); strServiceDisplayName = pESS->lpDisplayName; return S_OK; }
BSTR CServiceCookie::QueryResultColumnText( int nCol, CFileMgmtComponentData& refcdata ) { switch (nCol) { case COLNUM_SERVICES_SERVICENAME: return GetServiceStatus()->lpDisplayName; case COLNUM_SERVICES_DESCRIPTION: return const_cast<BSTR>((LPCTSTR)m_strDescription); case COLNUM_SERVICES_STATUS: return const_cast<BSTR>( Service_PszMapStateToName(m_dwCurrentState) ); case COLNUM_SERVICES_STARTUPTYPE: return const_cast<BSTR>( Service_PszMapStartupTypeToName(m_dwStartType) ); case COLNUM_SERVICES_SECURITYCONTEXT: return const_cast<BSTR>((LPCTSTR)m_strServiceStartName); default: ASSERT(FALSE); break; } return L""; }
class CServiceCookieBlock : public CCookieBlock<CServiceCookie>, public CStoresMachineName { public: inline CServiceCookieBlock( CServiceCookie* aCookies, // use vector ctor, we use vector dtor
INT cCookies, LPCTSTR lpcszMachineName, PVOID pvCookieData) : CCookieBlock<CServiceCookie>( aCookies, cCookies ), CStoresMachineName( lpcszMachineName ), m_pvCookieData(pvCookieData) { for (int i = 0; i < cCookies; i++) // {
// aCookies[i].ReadMachineNameFrom( (CHasMachineName*)this );
aCookies[i].m_pCookieBlock = this; // }
} virtual ~CServiceCookieBlock(); private: PVOID m_pvCookieData; // actually ENUM_SERVICE_STATUS*
};
DEFINE_COOKIE_BLOCK(CServiceCookie)
CServiceCookieBlock::~CServiceCookieBlock() { if (NULL != m_pvCookieData) { delete m_pvCookieData; m_pvCookieData = NULL; } }
void CServiceCookie::AddRefCookie() { m_pCookieBlock->AddRef(); } void CServiceCookie::ReleaseCookie() { m_pCookieBlock->Release(); }
DEFINE_FORWARDS_MACHINE_NAME( CServiceCookie, m_pCookieBlock ) */
int g_marker;
class CNewServiceCookie : public CNewResultCookie { public: // 581167-2002/03/05-JonN should initialize DWORD members
CNewServiceCookie() : CNewResultCookie( (PVOID)&g_marker, FILEMGMT_SERVICE ) , m_dwState( 0 ) , m_dwStartType( 0 ) {} virtual ~CNewServiceCookie();
virtual BSTR QueryResultColumnText( int nCol, CFileMgmtComponentData& refcdata ); virtual HRESULT CompareSimilarCookies(CCookie * pOtherCookie, int * pnResult); virtual HRESULT GetServiceName( OUT CString& strServiceName ); virtual HRESULT GetServiceDisplayName( OUT CString& strServiceName ); virtual HRESULT GetExplorerViewDescription( OUT CString& strExplorerViewDescription );
virtual HRESULT SimilarCookieIsSameObject( CNewResultCookie* pOtherCookie, BOOL* pbSame ); virtual BOOL CopySimilarCookie( CNewResultCookie* pcookie );
public: CString m_strServiceName; CString m_strDisplayName; CString m_strDescription; DWORD m_dwState; DWORD m_dwStartType; CString m_strStartName;
}; // CNewServiceCookie
CNewServiceCookie::~CNewServiceCookie() { }
BSTR CNewServiceCookie::QueryResultColumnText( int nCol, CFileMgmtComponentData& /*refcdata*/ ) { switch (nCol) { case COLNUM_SERVICES_SERVICENAME: return const_cast<BSTR>((LPCTSTR)m_strDisplayName); case COLNUM_SERVICES_DESCRIPTION: return const_cast<BSTR>((LPCTSTR)m_strDescription); case COLNUM_SERVICES_STATUS: return const_cast<BSTR>( Service_PszMapStateToName(m_dwState) ); case COLNUM_SERVICES_STARTUPTYPE: return const_cast<BSTR>( Service_PszMapStartupTypeToName(m_dwStartType) ); case COLNUM_SERVICES_SECURITYCONTEXT: // JonN 11/14/00 188203 support LocalService/NetworkService
return const_cast<BSTR>( Service_PszMapStartupAccountToName(m_strStartName) ); default: ASSERT(FALSE); break; } return L""; }
HRESULT CNewServiceCookie::CompareSimilarCookies(CCookie * pOtherCookie, int * pnResult) { if ( !pOtherCookie || FILEMGMT_SERVICE != QueryObjectType () ) { ASSERT(FALSE); return E_FAIL; }
CNewServiceCookie* pcookie = dynamic_cast <CNewServiceCookie*>(pOtherCookie); if ( FILEMGMT_SERVICE != pcookie->QueryObjectType () || !IsSameType(pcookie) ) { ASSERT(FALSE); return E_FAIL; }
int colNum = *pnResult; // save in case it's overwritten
HRESULT hr = CHasMachineName::CompareMachineNames( *pcookie, pnResult ); if (S_OK != hr || 0 != *pnResult) return hr;
switch (colNum) // column number
{ case COMPARESIMILARCOOKIE_FULL: // fall through
case COLNUM_SERVICES_SERVICENAME: *pnResult = lstrcmpi(m_strDisplayName, pcookie->m_strDisplayName); break;
case COLNUM_SERVICES_DESCRIPTION: *pnResult = lstrcmpi(m_strDescription, pcookie->m_strDescription); break;
case COLNUM_SERVICES_STATUS: { CString strServiceA = Service_PszMapStateToName(m_dwState); CString strServiceB = Service_PszMapStateToName(pcookie->m_dwState); *pnResult = lstrcmpi(strServiceA, strServiceB); } break;
case COLNUM_SERVICES_STARTUPTYPE: { CString strServiceA = Service_PszMapStartupTypeToName(m_dwStartType); CString strServiceB = Service_PszMapStartupTypeToName(pcookie->m_dwStartType); *pnResult = lstrcmpi(strServiceA, strServiceB); } break;
case COLNUM_SERVICES_SECURITYCONTEXT: // JonN 11/14/00 188203 support LocalService/NetworkService
{ CString strServiceA = Service_PszMapStartupAccountToName(m_strStartName); CString strServiceB = Service_PszMapStartupAccountToName(pcookie->m_strStartName); *pnResult = lstrcmpi(strServiceA, strServiceB); } break;
default: ASSERT(FALSE); return E_UNEXPECTED; }
return S_OK; }
HRESULT CNewServiceCookie::GetServiceName(OUT CString& strServiceName ) { strServiceName = m_strServiceName; return S_OK; }
HRESULT CNewServiceCookie::GetServiceDisplayName(OUT CString& strServiceDisplayName ) { strServiceDisplayName = m_strDisplayName; return S_OK; }
HRESULT CNewServiceCookie::GetExplorerViewDescription(OUT CString& strExplorerViewDescription ) { strExplorerViewDescription = m_strDescription; return S_OK; }
HRESULT CNewServiceCookie::SimilarCookieIsSameObject( CNewResultCookie* pOtherCookie, BOOL* pbSame ) { if ( !pOtherCookie || !IsSameType(pOtherCookie) ) { ASSERT(FALSE); return E_FAIL; }
int nResult = 0; HRESULT hr = CHasMachineName::CompareMachineNames( *pOtherCookie, &nResult ); if (S_OK != hr || 0 != nResult) { *pbSame = FALSE; return hr; } *pbSame = (0 == lstrcmpi(m_strServiceName, ((CNewServiceCookie*)pOtherCookie)->m_strServiceName) );
return S_OK; }
BOOL CNewServiceCookie::CopySimilarCookie( CNewResultCookie* pcookie ) { if (NULL == pcookie) { ASSERT(FALSE); return FALSE; } CNewServiceCookie* pnewcookie = (CNewServiceCookie*)pcookie; BOOL fChanged = FALSE; if (m_strServiceName != pnewcookie->m_strServiceName) { m_strServiceName = pnewcookie->m_strServiceName; fChanged = TRUE; } if (m_strDisplayName != pnewcookie->m_strDisplayName) { m_strDisplayName = pnewcookie->m_strDisplayName; fChanged = TRUE; } if (m_strDescription != pnewcookie->m_strDescription) { m_strDescription = pnewcookie->m_strDescription; fChanged = TRUE; } if (m_dwState != pnewcookie->m_dwState) { m_dwState = pnewcookie->m_dwState; fChanged = TRUE; } if (m_dwStartType != pnewcookie->m_dwStartType) { m_dwStartType = pnewcookie->m_dwStartType; fChanged = TRUE; } if (m_strStartName != pnewcookie->m_strStartName) { m_strStartName = pnewcookie->m_strStartName; fChanged = TRUE; } // don't bother with machine name
fChanged |= CNewResultCookie::CopySimilarCookie( pcookie ); return fChanged; }
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// Service_EOpenScManager()
//
// Open the service Service Control Manager database to
// enumerate all available services.
//
// If an error occured, return the error code returned by GetLastError(),
// otherwise return ERROR_SUCCESS.
//
APIERR CFileMgmtComponentData::Service_EOpenScManager(LPCTSTR pszMachineName) { Endorse(pszMachineName == NULL); // TRUE => Local machine
Assert(m_hScManager == NULL && "Service Control Manager should not have been opened yet");
APIERR dwErr = ERROR_SUCCESS; if (pszMachineName != NULL) { // 581209-2002/03/04 JonN handle L"\\" case
if (pszMachineName[0] == _T('\\') && pszMachineName[1] == _T('\\')) { // Get rid of the \\ at the beginning of machine name
pszMachineName += 2; } if (pszMachineName[0] == _T('\0')) pszMachineName = NULL; // Empty string == Local Machine
} CWaitCursor wait; m_hScManager = ::OpenSCManager( pszMachineName, NULL, SC_MANAGER_ENUMERATE_SERVICE); if (m_hScManager == NULL) { dwErr = ::GetLastError(); TRACE3("CFileMgmtComponentData::Service_OpenScManager() - " _T("Unable to open Service Control Manager database on machine %s. err=%d (0x%X).\n"), (pszMachineName != NULL) ? pszMachineName : _T("LocalMachine"), dwErr, dwErr); } return dwErr; } // CFileMgmtComponentData::Service_EOpenScManager()
/////////////////////////////////////////////////////////////////////
void CFileMgmtComponentData::Service_CloseScManager() { if (m_hScManager != NULL) { CWaitCursor wait; // Auto-wait cursor
(void)::CloseServiceHandle(m_hScManager); m_hScManager = NULL; } } // CFileMgmtComponentData::Service_CloseScManager()
/////////////////////////////////////////////////////////////////////
// CFileMgmtComponentData::Service_PopulateServices()
//
// Enumerate all available services and display them
// into the listview control.
//
// 12/03/98 JonN With the mark-and-sweep change, this no longer adds the items
// the the view
//
HRESULT CFileMgmtComponentData::Service_PopulateServices(LPRESULTDATA pResultData, CFileMgmtScopeCookie* pcookie) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); // required for CWaitCursor
TEST_NONNULL_PTR_PARAM(pResultData); TEST_NONNULL_PTR_PARAM(pcookie);
DWORD cbBytesNeeded = 0; // Number of necessary bytes to return all service entries
DWORD dwServicesReturned = 0; // Number of services returned
DWORD dwResumeHandle = 0; BOOL fRet; DWORD dwErr = ERROR_SUCCESS;
if (m_hScManager == NULL) { dwErr = Service_EOpenScManager(pcookie->QueryTargetServer()); } if (m_hScManager == NULL) { Assert(dwErr != ERROR_SUCCESS); DoServicesErrMsgBox(::GetActiveWindow(), MB_OK | MB_ICONEXCLAMATION, dwErr, IDS_MSG_s_UNABLE_TO_OPEN_SERVICE_DATABASE, pcookie->QueryNonNULLMachineName()); return S_OK; }
//
// The idea here is to ask the enum Api how much memory is
// needed to enumerate all services.
//
{ CWaitCursor wait; // Auto-wait cursor
fRet = ::EnumServicesStatus( m_hScManager, SERVICE_WIN32, // Type of services to enumerate
SERVICE_ACTIVE | SERVICE_INACTIVE, // State of services to enumerate
NULL, // Pointer to service status buffer
0, // Size of service status buffer
OUT &cbBytesNeeded, // Number of necessary bytes to return the remaining service entries
OUT &dwServicesReturned, // Number returned services
OUT &dwResumeHandle); // Pointer to variable for next entry (unused)
}
Report(fRet == FALSE); // First attempt should fail
Report(cbBytesNeeded > 0); // Add room for 10 extra services (just in case)
cbBytesNeeded += 10 * sizeof(ENUM_SERVICE_STATUS); // Allocate memory for the enumeration
ENUM_SERVICE_STATUS * prgESS = (ENUM_SERVICE_STATUS *) new BYTE[cbBytesNeeded]; //
// Now call the enum Api to retreive the services
//
{ CWaitCursor wait; // Auto-wait cursor
fRet = ::EnumServicesStatus( m_hScManager, SERVICE_WIN32, // Type of services to enumerate
SERVICE_ACTIVE | SERVICE_INACTIVE, // State of services to enumerate
OUT prgESS, // Pointer to service status buffer
IN cbBytesNeeded, // Size of service status buffer
OUT &cbBytesNeeded, // Number of necessary bytes to return the remaining service entries
OUT &dwServicesReturned, // Number of sercvices returned
OUT &dwResumeHandle); // Pointer to variable for next entry
dwErr = ::GetLastError(); } if (!fRet) { Assert(dwErr != ERROR_SUCCESS); DoServicesErrMsgBox(::GetActiveWindow(), MB_OK | MB_ICONEXCLAMATION, dwErr, IDS_MSG_s_UNABLE_TO_READ_SERVICES, pcookie->QueryNonNULLMachineName()); delete prgESS; return S_OK; // PREFIX ISSUE-2002/04/15-JonN should delete[] as BYTE*
} { CWaitCursor wait; // Auto-wait cursor
// Add the services to listview
Service_AddServiceItems(pResultData, pcookie, prgESS, dwServicesReturned); delete prgESS; // PREFIX ISSUE-2002/04/15-JonN should delete[] as BYTE*
} return S_OK; } // CFileMgmtComponentData::Service_PopulateServices()
/////////////////////////////////////////////////////////////////////
// CFileMgmtComponentData::Service_AddServiceItems()
//
// Insert service items to the result pane (listview control).
//
// 12/03/98 JonN With the mark-and-sweep change, this no longer adds the items
// the the view
// 04/07/02 JonN 544137: Rebuilt this function to handle extralong return buffers
//
HRESULT CFileMgmtComponentData::Service_AddServiceItems( LPRESULTDATA /*pResultData*/, CFileMgmtScopeCookie * pParentCookie, ENUM_SERVICE_STATUS * prgESS, // IN: Array of structures of services
DWORD nDataItems) // IN: Number of structures in prgESS
{ Assert(pParentCookie != NULL); Assert(prgESS != NULL);
CString str; BOOL fResult;
ASSERT(m_hScManager != NULL); // Service control manager should be already opened
DWORD cbActiveBufferSize = max(max(sizeof(QUERY_SERVICE_CONFIG), SERVICE_cbQueryServiceConfigMax), max(sizeof(SERVICE_DESCRIPTION), SERVICE_cchDescriptionMax * sizeof(TCHAR) + 16)); LPBYTE pActiveBuffer = new BYTE[cbActiveBufferSize]; if (NULL == pActiveBuffer) { ASSERT(FALSE); return ERROR_NOT_ENOUGH_MEMORY; }
for ( ; nDataItems > 0; nDataItems--, prgESS++ ) { /*
** Add one line per service */
// Open service to get its configuration
SC_HANDLE hService = ::OpenService( m_hScManager, prgESS->lpServiceName, SERVICE_QUERY_CONFIG); if (hService == NULL) { TRACE2("Failed to open service %s. err=%u.\n", prgESS->lpServiceName, ::GetLastError()); }
// Query config description
DWORD cbBytesNeeded = 0; CString strDescription; if (m_fQueryServiceConfig2 && NULL != hService) { // We only call this API if it is supported by target machine
// JonN-2002/04/04-544089 ensure NULL-termination
::ZeroMemory(pActiveBuffer, cbActiveBufferSize); fResult = ::MyQueryServiceConfig2( &m_fQueryServiceConfig2, hService, SERVICE_CONFIG_DESCRIPTION, OUT pActiveBuffer, cbActiveBufferSize, OUT &cbBytesNeeded); if ( !fResult && m_fQueryServiceConfig2 && ERROR_INSUFFICIENT_BUFFER == ::GetLastError()) { if (cbBytesNeeded <= cbActiveBufferSize || cbBytesNeeded > 100000) { ASSERT(FALSE); // inappropriate size request
} else { // try to reallocate larger buffer
LPBYTE pNewActiveBuffer = new BYTE[cbBytesNeeded+1000]; if (NULL == pNewActiveBuffer) { Report("FILEMGMT: Cannot reallocate MyQueryServiceConfig2 buffer: out of memory"); } else { // larger buffer allocated, start using it
delete[] pActiveBuffer; pActiveBuffer = pNewActiveBuffer; cbActiveBufferSize = cbBytesNeeded+1000;
// retry API
::ZeroMemory(pActiveBuffer, cbActiveBufferSize); cbBytesNeeded = 0; fResult = ::MyQueryServiceConfig2( &m_fQueryServiceConfig2, hService, SERVICE_CONFIG_DESCRIPTION, OUT pActiveBuffer, cbActiveBufferSize, OUT &cbBytesNeeded); } // larger buffer allocated
} // appropriate size request
} // ERROR_INSUFFICIENT_BUFFER
if (!fResult) { if (!m_fQueryServiceConfig2) { // the local machine does not support QueryServiceConfig2
// CODEWORK How could we get here anyhow? JonN 1/31/97
} else { // This is probably because the target machine is running
// an older version of NT not supporting this API.
DWORD dwErr = ::GetLastError(); TRACE2("QueryServiceConfig2(%s) failed. err=%u.\n", prgESS->lpServiceName, dwErr); TRACE1("INFO: Machine %s does not support QueryServiceConfig2() API.\n", pParentCookie->QueryTargetServer() ? pParentCookie->QueryTargetServer() : _T("(Local)")); Report(dwErr == RPC_S_PROCNUM_OUT_OF_RANGE && "Unusual Situation: Expected error should be RPC_S_PROCNUM_OUT_OF_RANGE"); Report(m_fQueryServiceConfig2 != FALSE && "How can this happen???"); m_fQueryServiceConfig2 = FALSE; } } else // fResult is true
{ // MyQueryServiceConfig2 succeeded
// We limit the length of the service description to 1000 characters
// otherwise mmc.exe will AV.
// CODEWORK remove this when the bug is fixed in MMC
SERVICE_DESCRIPTION* psd = (SERVICE_DESCRIPTION*)pActiveBuffer; if (NULL != psd->lpDescription) { if (lstrlen(psd->lpDescription) >= 1000) { TRACE1("INFO: Description of service %s is too long. Only the first 1000 characters will be displayed.\n", prgESS->lpServiceName); psd->lpDescription[1000] = _T('\0'); } strDescription = psd->lpDescription; } // if (NULL != psd->lpDescription)
} // if (fResult is true)
} // if (m_fQueryServiceConfig2 && NULL != hService)
// Query service config
// This might fail e.g. if insufficient permissions
BOOL fQSCResult = FALSE; QUERY_SERVICE_CONFIG* pqsc = (QUERY_SERVICE_CONFIG*)pActiveBuffer; if (NULL != hService) { cbBytesNeeded = 0; ::ZeroMemory(pActiveBuffer, cbActiveBufferSize); fQSCResult = ::QueryServiceConfig( hService, OUT pqsc, cbActiveBufferSize, OUT &cbBytesNeeded); // JonN-2002/04/04-544089 handle long DisplayName value
if (!fQSCResult && ERROR_INSUFFICIENT_BUFFER == ::GetLastError()) { if (cbBytesNeeded <= cbActiveBufferSize || cbBytesNeeded > 100000) { ASSERT(FALSE); // inappropriate size request
} else { // try to reallocate larger buffer
LPBYTE pNewActiveBuffer = new BYTE[cbBytesNeeded+1000]; if (NULL == pNewActiveBuffer) { Report("FILEMGMT: Cannot reallocate QueryServiceConfig buffer: out of memory"); } else { // larger buffer allocated, start using it
delete[] pActiveBuffer; pActiveBuffer = pNewActiveBuffer; cbActiveBufferSize = cbBytesNeeded+1000;
// retry API
::ZeroMemory(pActiveBuffer, cbActiveBufferSize); cbBytesNeeded = 0; pqsc = (QUERY_SERVICE_CONFIG*)pActiveBuffer; cbBytesNeeded = 0; ::ZeroMemory(pActiveBuffer, cbActiveBufferSize); fQSCResult = ::QueryServiceConfig( hService, OUT pqsc, cbActiveBufferSize, OUT &cbBytesNeeded); } // larger buffer allocated
} // appropriate size request
} // ERROR_INSUFFICIENT_BUFFER
} // if (NULL != hService)
// Add the first column
CNewServiceCookie * pnewcookie = new CNewServiceCookie; pnewcookie->m_strServiceName = prgESS->lpServiceName; pnewcookie->m_strDisplayName = prgESS->lpDisplayName; pnewcookie->m_strDescription = strDescription; pnewcookie->m_dwState = prgESS->ServiceStatus.dwCurrentState; pnewcookie->m_dwStartType = ((!fQSCResult) ? (DWORD)-1 : pqsc->dwStartType);
// JonN 4/11/00 17756: The description of "Account Run under" is unlocalized.
// Display empty string instead of "LocalSystem"
pnewcookie->m_strStartName = ((!fQSCResult || !lstrcmpi(L"LocalSystem",pqsc->lpServiceStartName)) ? NULL : pqsc->lpServiceStartName);
pnewcookie->SetMachineName( pParentCookie->QueryTargetServer() ); pParentCookie->ScanAndAddResultCookie( pnewcookie );
if (NULL != hService) { VERIFY(::CloseServiceHandle(hService)); } } // for
if (pActiveBuffer) delete[] pActiveBuffer;
return S_OK;
} // CFileMgmtComponentData::Service_AddServiceItems()
/////////////////////////////////////////////////////////////////////
// CFileMgmtComponentData::Service_FGetServiceInfoFromIDataObject()
//
// Extract 'machine name', 'service name' and/or 'service display name'
// from the data object.
//
// Return FALSE if data could not be retrived, otherwise return TRUE.
//
BOOL CFileMgmtComponentData::Service_FGetServiceInfoFromIDataObject( IDataObject * pDataObject, // IN: Data object
CString * pstrMachineName, // OUT: OPTIONAL: Machine name
CString * pstrServiceName, // OUT: OPTIONAL: Service name
CString * pstrServiceDisplayName) // OUT: OPTIONAL: Service display name
{ // ISSUE-2002/03/05-JonN should handle this case better
Assert(pDataObject != NULL); Endorse(pstrMachineName == NULL); Endorse(pstrServiceName == NULL); Endorse(pstrServiceDisplayName == NULL);
HRESULT hr; BOOL fSuccess = TRUE;
if (pstrMachineName != NULL) { // Get the machine name (computer name) from IDataObject
hr = ::ExtractString( pDataObject, CFileMgmtDataObject::m_CFMachineName, OUT pstrMachineName, DNS_MAX_NAME_BUFFER_LENGTH); if (FAILED(hr)) { TRACE0("CFileMgmtComponentData::Service_FGetServiceInfoFromIDataObject() - Failed to get machine name.\n"); fSuccess = FALSE; } } // if
if (pstrServiceName != NULL) { // Get the service name from IDataObject
hr = ::ExtractString( pDataObject, CFileMgmtDataObject::m_CFServiceName, OUT pstrServiceName, 255); if (FAILED(hr) || pstrServiceName->IsEmpty()) { TRACE0("CFileMgmtComponentData::Service_FGetServiceInfoFromIDataObject() - Failed to get service name.\n"); fSuccess = FALSE; } } // if
if (pstrServiceDisplayName != NULL) { // Get the service display name from IDataObject
hr = ::ExtractString( pDataObject, CFileMgmtDataObject::m_CFServiceDisplayName, OUT pstrServiceDisplayName, 255); if (FAILED(hr) || pstrServiceDisplayName->IsEmpty()) { TRACE0("CFileMgmtComponentData::Service_FGetServiceInfoFromIDataObject() - Failed to get service display name\n"); fSuccess = FALSE; } } // if
return fSuccess; } // CFileMgmtComponentData::Service_FGetServiceInfoFromIDataObject()
/////////////////////////////////////////////////////////////////////
// CFileMgmtComponentData::Service_FAddMenuItems()
//
// Add menuitems to the service context menu.
// The same routine will be used to extend context menus of
// others snapins who wants to have "Start", "Stop", "Pause",
// "Resume" and "Restart" menuitems.
//
// Return TRUE if successful, otherwise FALSE.
//
BOOL CFileMgmtComponentData::Service_FAddMenuItems( IContextMenuCallback * pContextMenuCallback, // OUT: Object to append menuitems
IDataObject * pDataObject, // IN: Data object
BOOL fIs3rdPartyContextMenuExtension) // IN: TRUE => Add the menu items as a 3rd party extension
{ AFX_MANAGE_STATE(AfxGetStaticModuleState( )); // required for CWaitCursor
Assert(pContextMenuCallback != NULL); Assert(pDataObject != NULL); Endorse(m_hScManager == NULL); // TRUE => Network connection was broken
CString strMachineName; CString strServiceName; CString strServiceDisplayName; BOOL fSuccess = TRUE;
if (!Service_FGetServiceInfoFromIDataObject( pDataObject, OUT &strMachineName, OUT &strServiceName, OUT &strServiceDisplayName)) { TRACE0("CFileMgmtComponentData::Service_FAddMenuItems() - Unable to query IDataObject for correct clipboard format.\n"); return FALSE; } if (fIs3rdPartyContextMenuExtension) { Assert(m_hScManager == NULL); // ISSUE-2002/03/05-JonN should use CWaitCursor
if (m_hScManager == NULL) (void)Service_EOpenScManager(strMachineName); }
BOOL rgfMenuFlags[iServiceActionMax]; { //
// Get the menu flags
//
CWaitCursor wait; if (!Service_FGetServiceButtonStatus( m_hScManager, strServiceName, OUT rgfMenuFlags, NULL, // pdwCurrentState
TRUE)) // fSilentError
{ // Nothing to do here
} } if (strMachineName.IsEmpty()) strMachineName = g_strLocalMachine; if (strServiceDisplayName.IsEmpty()) strServiceDisplayName = g_strUnknown; CString strMenuItem; CString strStatusBar;
CComQIPtr<IContextMenuCallback2, &IID_IContextMenuCallback2> spContextMenuCallback2 = pContextMenuCallback;
// Add the menu items
for (INT i = iServiceActionStart; i < iServiceActionMax; i++) { LoadStringWithInsertions(IDS_SVC_MENU_SERVICE_START + i, OUT &strMenuItem); LoadStringWithInsertions(IDS_SVC_STATUSBAR_ss_SERVICE_START + i, OUT &strStatusBar, (LPCTSTR)strServiceDisplayName, (LPCTSTR)strMachineName);
CONTEXTMENUITEM2 contextmenuitem; ::ZeroMemory(OUT &contextmenuitem, sizeof(contextmenuitem)); // ISSUE-2002/03/05-JonN remote USES_CONVERSION and T2OLE
// I don't trust this, doesn't T2OLE reuse a global buffer?
USES_CONVERSION; contextmenuitem.strName = T2OLE(const_cast<LPTSTR>((LPCTSTR)strMenuItem)); contextmenuitem.strStatusBarText = T2OLE(const_cast<LPTSTR>((LPCTSTR)strStatusBar)); contextmenuitem.lCommandID = cmServiceStart + i; contextmenuitem.lInsertionPointID = fIs3rdPartyContextMenuExtension ? CCM_INSERTIONPOINTID_3RDPARTY_TASK : CCM_INSERTIONPOINTID_PRIMARY_TOP; contextmenuitem.fFlags = rgfMenuFlags[i] ? MF_ENABLED : MF_GRAYED;
// JonN 4/18/00 Explorer View requires Callback2
static LPTSTR astrLanguageIndependentMenuNames[iServiceActionMax] = { _T("Start"), _T("Stop"), _T("Pause"), _T("Resume"), _T("Restart") }; contextmenuitem.strLanguageIndependentName = astrLanguageIndependentMenuNames[i];
HRESULT hr = S_OK; if (spContextMenuCallback2) hr = spContextMenuCallback2->AddItem( &contextmenuitem ); else hr = pContextMenuCallback->AddItem( (CONTEXTMENUITEM*)(&contextmenuitem) ); ASSERT( SUCCEEDED(hr) && "Unable to add menu item" );
if ( !fIs3rdPartyContextMenuExtension ) { contextmenuitem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TASK; if (spContextMenuCallback2) hr = spContextMenuCallback2->AddItem( &contextmenuitem ); else hr = pContextMenuCallback->AddItem( (CONTEXTMENUITEM*)(&contextmenuitem) ); ASSERT( SUCCEEDED(hr) && "Unable to add menu item" ); } } // for
return fSuccess; } // CFileMgmtComponentData::Service_FAddMenuItems()
/////////////////////////////////////////////////////////////////////
// CFileMgmtComponentData::Service_FDispatchMenuCommand()
//
// Dispatch a menu command for a given service
//
// Return TRUE if result pane need to be updated, otherwise FALSE.
//
// We might get a cmStart command on a paused service, if the command
// came from the toolbar. For that matter, we might get a command
// on a non-service, until we fix the toolbar button updating.
//
BOOL CFileMgmtComponentData::Service_FDispatchMenuCommand( INT nCommandId, IDataObject * pDataObject) { Assert(pDataObject != NULL); Endorse(m_hScManager == NULL);
CString strMachineName; CString strServiceName; CString strServiceDisplayName; DWORD dwLastError;
if (!Service_FGetServiceInfoFromIDataObject( pDataObject, OUT &strMachineName, OUT &strServiceName, OUT &strServiceDisplayName)) { TRACE0("CFileMgmtComponentData::Service_FDispatchMenuCommand() - Unable to read data from IDataObject.\n"); return FALSE; }
if (m_hScManager == NULL) { TRACE0("CFileMgmtComponentData::Service_FDispatchMenuCommand() - Handle m_hScManager is NULL.\n"); return FALSE; } if (nCommandId == cmServiceStart || nCommandId == cmServiceStartTask ) { dwLastError = CServiceControlProgress::S_EStartService( ::GetActiveWindow(), m_hScManager, strMachineName, strServiceName, strServiceDisplayName, 0, NULL); // no startup parameters passed from menu command
} else { DWORD dwControlCode; switch (nCommandId) { default: Assert(FALSE); // fall through
case cmServiceStop: case cmServiceStopTask: dwControlCode = SERVICE_CONTROL_STOP; break;
case cmServicePause: case cmServicePauseTask: dwControlCode = SERVICE_CONTROL_PAUSE; break;
case cmServiceResume: case cmServiceResumeTask: dwControlCode = SERVICE_CONTROL_CONTINUE; break;
case cmServiceRestart: case cmServiceRestartTask: dwControlCode = SERVICE_CONTROL_RESTART; break; } // switch
dwLastError = CServiceControlProgress::S_EControlService( ::GetActiveWindow(), m_hScManager, strMachineName, strServiceName, strServiceDisplayName, dwControlCode);
} // if...else
// We do want to to keep the connection opened
return (dwLastError != CServiceControlProgress::errUserCancelStopDependentServices); } // CFileMgmtComponentData::Service_FDispatchMenuCommand()
/////////////////////////////////////////////////////////////////////
// CFileMgmtComponentData::Service_FInsertPropertyPages()
//
// Insert property pages of the data object (service).
//
// Return TRUE if successful, otherwise FALSE.
//
// IMPLEMENTATION NOTES
// The routine allocates a CServicePropertyData object which
// is auto-deleted by the property sheet. The property sheet will
// delete the CServicePropertyData object on its WM_DESTROY message.
//
BOOL CFileMgmtComponentData::Service_FInsertPropertyPages( LPPROPERTYSHEETCALLBACK pCallBack, // OUT: Object to append property pages
IDataObject * pDataObject, // IN: Data object
LONG_PTR lNotifyHandle) // IN: Handle to notify the parent
{ Assert(pCallBack != NULL); Assert(pDataObject != NULL); Endorse(m_hScManager != NULL);
if (m_hScManager == NULL) { // Typically because network connection was broken
TRACE0("INFO: m_hScManager is NULL.\n"); return FALSE; }
CString strMachineName; CString strServiceName; CString strServiceDisplayName;
if (!Service_FGetServiceInfoFromIDataObject( pDataObject, OUT &strMachineName, OUT &strServiceName, OUT &strServiceDisplayName)) { Assert(FALSE); return FALSE; }
CServicePropertyData * pSPD = new CServicePropertyData; if (!pSPD->FInit( pDataObject, strMachineName, strServiceName, strServiceDisplayName, lNotifyHandle)) { TRACE1("Failure to query service %s.\n", (LPCTSTR)strServiceName); delete pSPD; return FALSE; } return pSPD->CreatePropertyPages(pCallBack); } // CFileMgmtComponentData::Service_FInsertPropertyPages()
#ifdef SNAPIN_PROTOTYPER
#include "protyper.cpp"
#endif
|