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.
 
 
 
 
 
 

1100 lines
33 KiB

/////////////////////////////////////////////////////////////////////
//
// 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