|
|
//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1995
//
// File: cserv.cxx
//
// Contents: Contains methods for the following objects
// CWinNTService,
//
// History: 12/11/95 ramv (Ram Viswanathan) Created.
//
//----------------------------------------------------------------------------
#include "winnt.hxx"
#pragma hdrstop
#define INITGUID
//
// class CWinNTService methods
//
DEFINE_IDispatch_ExtMgr_Implementation(CWinNTService); DEFINE_IADsExtension_ExtMgr_Implementation(CWinNTService); DEFINE_IADs_TempImplementation(CWinNTService); DEFINE_IADs_PutGetImplementation(CWinNTService,ServiceClass,gdwServiceTableSize); DEFINE_IADsPropertyList_Implementation(CWinNTService, ServiceClass,gdwServiceTableSize)
CWinNTService::CWinNTService() { _pDispMgr = NULL; _pExtMgr = NULL; _pPropertyCache = NULL;
_pszServiceName = NULL; _pszServerName = NULL; _pszPath = NULL;
_schSCManager = NULL; _schService = NULL; _dwWaitHint = 0; _dwCheckPoint = 0; _fValidHandle = FALSE;
ENLIST_TRACKING(CWinNTService); }
CWinNTService::~CWinNTService() { if(_fValidHandle){ //
// an open handle exists, blow it away
//
WinNTCloseService(); _fValidHandle = FALSE; }
if(_pszServiceName){ FreeADsStr(_pszServiceName); }
if(_pszServerName){ FreeADsStr(_pszServerName); }
if(_pszPath){ FreeADsStr(_pszPath); }
delete _pExtMgr; // created last, destroyed first
delete _pDispMgr;
delete _pPropertyCache; return; }
//+---------------------------------------------------------------------------
//
// Function: CWinNTService::Create
//
// Synopsis: Static function used to create a Service object. This
// will be called by BindToObject
//
// Arguments: [ppWinNTService] -- Ptr to a ptr to a new Service object.
//
// Returns: HRESULT.
//
// Modifies:
//
// History: 12-11-95 RamV Created.
//
//----------------------------------------------------------------------------
HRESULT CWinNTService::Create(LPTSTR pszADsParent, LPTSTR pszDomainName, LPTSTR pszServerName, LPTSTR pszServiceName, DWORD dwObjectState, REFIID riid, CWinNTCredentials& Credentials, LPVOID * ppvoid )
{ CWinNTService FAR * pCWinNTService = NULL; HRESULT hr;
//
// Create the Service Object
//
hr = AllocateServiceObject(pszServerName, pszServiceName, &pCWinNTService);
BAIL_ON_FAILURE(hr);
ADsAssert(pCWinNTService->_pDispMgr);
hr = pCWinNTService->InitializeCoreObject(pszADsParent, pszServiceName, SERVICE_CLASS_NAME, SERVICE_SCHEMA_NAME, CLSID_WinNTService, dwObjectState);
BAIL_ON_FAILURE(hr);
hr = SetLPTSTRPropertyInCache(pCWinNTService->_pPropertyCache, TEXT("HostComputer"), pCWinNTService->_Parent, TRUE );
BAIL_ON_FAILURE(hr);
pCWinNTService->_Credentials = Credentials; hr = pCWinNTService->_Credentials.RefServer(pszServerName); BAIL_ON_FAILURE(hr);
//
// Load ext mgr and extensions
//
hr = ADSILoadExtensionManager( SERVICE_CLASS_NAME, (IADsService *) pCWinNTService, pCWinNTService->_pDispMgr, Credentials, &pCWinNTService->_pExtMgr ); BAIL_ON_FAILURE(hr);
ADsAssert(pCWinNTService->_pExtMgr);
// check if the call is from UMI
if(Credentials.GetFlags() & ADS_AUTH_RESERVED) { //
// we do not pass riid to InitUmiObject below. This is because UMI object
// does not support IDispatch. There are several places in ADSI code where
// riid passed into this function is defaulted to IID_IDispatch -
// IADsContainer::Create for example. To handle these cases, we always
// request IID_IUnknown from the UMI object. Subsequent code within UMI
// will QI for the appropriate interface.
//
if(3 == pCWinNTService->_dwNumComponents) { pCWinNTService->_CompClasses[0] = L"Domain"; pCWinNTService->_CompClasses[1] = L"Computer"; pCWinNTService->_CompClasses[2] = L"Service"; } else if(2 == pCWinNTService->_dwNumComponents) { // no workstation services
pCWinNTService->_CompClasses[0] = L"Computer"; pCWinNTService->_CompClasses[1] = L"Service"; } else BAIL_ON_FAILURE(hr = UMI_E_FAIL); hr = pCWinNTService->InitUmiObject( pCWinNTService->_Credentials, ServiceClass, gdwServiceTableSize, pCWinNTService->_pPropertyCache, (IUnknown *)(INonDelegatingUnknown *) pCWinNTService, pCWinNTService->_pExtMgr, IID_IUnknown, ppvoid );
BAIL_ON_FAILURE(hr);
//
// UMI object was created and the interface was obtained successfully.
// UMI object now has a reference to the inner unknown of IADs, since
// the call to Release() below is not going to be made in this case.
//
RRETURN(hr); }
hr = pCWinNTService->QueryInterface(riid, (void **)ppvoid); BAIL_ON_FAILURE(hr);
pCWinNTService->Release();
RRETURN(hr);
error:
delete pCWinNTService; RRETURN_EXP_IF_ERR(hr); }
HRESULT CWinNTService::AllocateServiceObject( LPTSTR pszServerName, LPTSTR pszServiceName, CWinNTService ** ppService ) { CWinNTService FAR * pService = NULL; HRESULT hr = S_OK;
pService = new CWinNTService(); if (pService == NULL) { hr = E_OUTOFMEMORY; } BAIL_ON_FAILURE(hr);
pService->_pDispMgr = new CAggregatorDispMgr; if (pService->_pDispMgr == NULL) { hr = E_OUTOFMEMORY; } BAIL_ON_FAILURE(hr);
pService->_pszServerName = AllocADsStr(pszServerName);
if(!(pService->_pszServerName)){ hr = E_OUTOFMEMORY; goto error; }
pService->_pszServiceName = AllocADsStr(pszServiceName);
if(!(pService->_pszServiceName)){ hr = E_OUTOFMEMORY; goto error; }
hr = LoadTypeInfoEntry(pService->_pDispMgr, LIBID_ADs, IID_IADsService, (IADsService *)pService, DISPID_REGULAR ); BAIL_ON_FAILURE(hr);
hr = LoadTypeInfoEntry(pService->_pDispMgr, LIBID_ADs, IID_IADsServiceOperations, (IADsServiceOperations *)pService, DISPID_REGULAR ); BAIL_ON_FAILURE(hr);
hr = CPropertyCache::createpropertycache( ServiceClass, gdwServiceTableSize, (CCoreADsObject *)pService, &(pService->_pPropertyCache) );
BAIL_ON_FAILURE(hr);
(pService->_pDispMgr)->RegisterPropertyCache( pService->_pPropertyCache );
*ppService = pService;
RRETURN(hr);
error:
//
// direct memeber assignement assignement at pt of creation, so
// do NOT delete _pPropertyCache or _pDisMgr here to avoid attempt
// of deletion again in pPrintJob destructor and AV
//
delete pService;
RRETURN(hr);
}
/* IUnknown methods for service object */
//----------------------------------------------------------------------------
// Function: QueryInterface
//
// Synopsis: If this object is aggregated within another object, then
// all calls will delegate to the outer object. Otherwise, the
// non-delegating QI is called
//
// Arguments:
//
// iid interface requested
// ppInterface Returns pointer to interface requested. NULL if interface
// is not supported.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *ppInterface to return interface pointer
//
//----------------------------------------------------------------------------
STDMETHODIMP CWinNTService::QueryInterface( REFIID iid, LPVOID *ppInterface ) { if(_pUnkOuter != NULL) RRETURN(_pUnkOuter->QueryInterface( iid, ppInterface ));
RRETURN(NonDelegatingQueryInterface( iid, ppInterface )); }
//----------------------------------------------------------------------------
// Function: AddRef
//
// Synopsis: IUnknown::AddRef. If this object is aggregated within
// another, all calls will delegate to the outer object.
// Otherwise, the non-delegating AddRef is called
//
// Arguments:
//
// None
//
// Returns: New reference count
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CWinNTService::AddRef(void) { if(_pUnkOuter != NULL) RRETURN(_pUnkOuter->AddRef());
RRETURN(NonDelegatingAddRef()); }
//----------------------------------------------------------------------------
// Function: Release
//
// Synopsis: IUnknown::Release. If this object is aggregated within
// another, all calls will delegate to the outer object.
// Otherwise, the non-delegating Release is called
//
// Arguments:
//
// None
//
// Returns: New reference count
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CWinNTService::Release(void) { if(_pUnkOuter != NULL) RRETURN(_pUnkOuter->Release());
RRETURN(NonDelegatingRelease()); }
//----------------------------------------------------------------------------
STDMETHODIMP CWinNTService::NonDelegatingQueryInterface(REFIID riid, LPVOID FAR* ppvObj) { HRESULT hr = S_OK;
if(!ppvObj){ RRETURN(E_POINTER); } if (IsEqualIID(riid, IID_IUnknown)) { *ppvObj = (IADsService *)this; }
else if (IsEqualIID(riid, IID_IDispatch)) { *ppvObj = (IADsService *)this; }
else if (IsEqualIID(riid, IID_ISupportErrorInfo)) { *ppvObj = (ISupportErrorInfo FAR *)this; } else if (IsEqualIID(riid, IID_IADsPropertyList)) { *ppvObj = (IADsPropertyList *)this; } else if (IsEqualIID(riid, IID_IADs)) { *ppvObj = (IADsService FAR *) this; } else if (IsEqualIID(riid, IID_IADsService)) { *ppvObj = (IADsService FAR *) this; } else if (IsEqualIID(riid, IID_IADsServiceOperations)) { *ppvObj = (IADsServiceOperations FAR *) this; } else if( (_pDispatch != NULL) && IsEqualIID(riid, IID_IADsExtension) ) { *ppvObj = (IADsExtension *) this; } else if (_pExtMgr) { RRETURN( _pExtMgr->QueryInterface(riid, ppvObj)); } else { *ppvObj = NULL; RRETURN(E_NOINTERFACE); } ((LPUNKNOWN)*ppvObj)->AddRef(); RRETURN(S_OK); }
/* ISupportErrorInfo method */ STDMETHODIMP CWinNTService::InterfaceSupportsErrorInfo( THIS_ REFIID riid ) { if (IsEqualIID(riid, IID_IADs) || IsEqualIID(riid, IID_IADsService) || IsEqualIID(riid, IID_IADsServiceOperations) || IsEqualIID(riid, IID_IADsPropertyList)) { RRETURN(S_OK); } else { RRETURN(S_FALSE); } }
//+---------------------------------------------------------------------------
//
// Function: SetInfo
//
// Synopsis:
//
// Arguments: void
//
// Returns: HRESULT.
//
// Modifies:
//
// History: RamV Created
//----------------------------------------------------------------------------
STDMETHODIMP CWinNTService::SetInfo(THIS) { HRESULT hr = S_OK; DWORD dwServiceType; DWORD dwStartType; DWORD dwErrorControl; LPTSTR pszPath = NULL; LPTSTR pszLoadOrderGroup = NULL; LPTSTR pszServiceStartName = NULL; LPTSTR pszDependencies = NULL; LPTSTR pszDisplayName = NULL; SC_LOCK sclLock = NULL; BOOL fRetval = FALSE; LPQUERY_SERVICE_CONFIG lpqServiceConfig = NULL;
if (GetObjectState() == ADS_OBJECT_UNBOUND) { hr = WinNTAddService(); BAIL_IF_ERROR(hr);
SetObjectState(ADS_OBJECT_BOUND);
}
hr = WinNTOpenService(SC_MANAGER_ALL_ACCESS, SERVICE_ALL_ACCESS);
BAIL_IF_ERROR(hr);
hr = GetServiceConfigInfo(&lpqServiceConfig);
BAIL_IF_ERROR(hr);
hr = GetLPTSTRPropertyFromCache( _pPropertyCache, TEXT("Path"), &pszPath ); if(SUCCEEDED(hr)){ lpqServiceConfig->lpBinaryPathName = pszPath; }
hr = GetLPTSTRPropertyFromCache( _pPropertyCache, TEXT("LoadOrderGroup"), &pszLoadOrderGroup ); if(SUCCEEDED(hr)){
lpqServiceConfig->lpLoadOrderGroup = pszLoadOrderGroup; }
hr = GetNulledStringPropertyFromCache( _pPropertyCache, TEXT("Dependencies"), &pszDependencies ); if(SUCCEEDED(hr)){
lpqServiceConfig->lpDependencies = pszDependencies; }
//
// Issue: Service Account Name property has been disabled from being a
// writeable property because ChangeServiceConfig AVs services.exe
// on the server machine when this property is changed
// RamV - Aug-11-96.
/*
hr = GetLPTSTRPropertyFromCache( _pPropertyCache, TEXT("ServiceAccountName"), &pszServiceStartName ); if(SUCCEEDED(hr)){
lpqServiceConfig->lpServiceStartName = pszServiceStartName; }
*/
hr = GetLPTSTRPropertyFromCache( _pPropertyCache, TEXT("DisplayName"), &pszDisplayName ); if(SUCCEEDED(hr)){
lpqServiceConfig->lpDisplayName = pszDisplayName; }
hr = GetDWORDPropertyFromCache( _pPropertyCache, TEXT("ServiceType"), &dwServiceType ); if(SUCCEEDED(hr)){
lpqServiceConfig->dwServiceType = dwServiceType; }
hr = GetDWORDPropertyFromCache( _pPropertyCache, TEXT("StartType"), &dwStartType ); if(SUCCEEDED(hr)){
lpqServiceConfig->dwStartType = dwStartType; }
hr = GetDWORDPropertyFromCache( _pPropertyCache, TEXT("ErrorControl"), &dwErrorControl ); if(SUCCEEDED(hr)){
lpqServiceConfig->dwErrorControl = dwErrorControl; }
//
// set hr to S_OK. why? we dont care about the errors we hit so far
//
hr = S_OK;
//
// put a lock on the database corresponding to this service
//
sclLock = LockServiceDatabase(_schSCManager);
if(sclLock == NULL){ //
// Exit if database cannot be locked
//
hr = HRESULT_FROM_WIN32(GetLastError()); goto cleanup; }
//
// change the service configuration. Pass in all the changed parameters.
// Since there is but one info level for services, use the
// internal values as parameters.
//
fRetval = ChangeServiceConfig(_schService, lpqServiceConfig->dwServiceType, lpqServiceConfig->dwStartType, lpqServiceConfig->dwErrorControl, lpqServiceConfig->lpBinaryPathName, lpqServiceConfig->lpLoadOrderGroup, NULL, lpqServiceConfig->lpDependencies, lpqServiceConfig->lpServiceStartName, NULL, lpqServiceConfig->lpDisplayName );
if (fRetval == FALSE) { hr = HRESULT_FROM_WIN32(GetLastError()); }
if(SUCCEEDED(hr)) _pPropertyCache->ClearModifiedFlags();
cleanup:
if(lpqServiceConfig){ FreeADsMem(lpqServiceConfig); }
if(sclLock){ UnlockServiceDatabase(sclLock); }
WinNTCloseService();
if(pszPath){ FreeADsStr(pszPath); }
if(pszLoadOrderGroup){ FreeADsStr(pszLoadOrderGroup); } if(pszServiceStartName){ FreeADsStr(pszServiceStartName); } if(pszDependencies){ FreeADsStr(pszDependencies); } if(pszDisplayName){ FreeADsStr(pszDisplayName); }
RRETURN_EXP_IF_ERR(hr); }
//+---------------------------------------------------------------------------
//
// Function: GetInfo
//
// Synopsis: Currently implemented
//
// Arguments: void
//
// Returns: HRESULT.
//
// Modifies:
//
// History: 12/11/95 RamV Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CWinNTService::GetInfo(THIS) {
RRETURN (GetInfo(1, TRUE));
}
STDMETHODIMP CWinNTService::ImplicitGetInfo(THIS) {
RRETURN (GetInfo(1, FALSE));
}
//+---------------------------------------------------------------------------
//
// Function: CWinNTService::GetInfo
//
// Synopsis: Binds to real Service as specified in _ServiceName and
// attempts to refresh the Service object from the real Service.
//
// Arguments: dwApiLevel (ignored), fExplicit (ignored)
//
// Returns: HRESULT.
//
// Modifies:
//
// History: 01/08/96 RamV Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CWinNTService::GetInfo(THIS_ DWORD dwApiLevel, BOOL fExplicit) { HRESULT hr; LPQUERY_SERVICE_CONFIG pMem = NULL; BYTE FastConfigInfo[256]; SERVICE_STATUS ssStatusInfo; DWORD dwBufAllocated = 256; DWORD dwBufNeeded; DWORD dwLastError; BOOL fRetval;
//
// GETTING NT SERVICE INFO
//
// Getting information about an NT service requires three calls.
// One to get configuration information, and one to get current
// status information, and one to get security information.
//
//
// Open the service
//
hr = WinNTOpenService(SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS, GENERIC_READ );
if (FAILED(hr)) { RRETURN_EXP_IF_ERR(hr); }
//
// Query for Service Status first.
//
fRetval = QueryServiceStatus(_schService, &ssStatusInfo );
if (fRetval == FALSE) { hr = HRESULT_FROM_WIN32(GetLastError());
WinNTCloseService(); goto cleanup; }
fRetval = QueryServiceConfig(_schService, (LPQUERY_SERVICE_CONFIG)(&FastConfigInfo), dwBufAllocated, &dwBufNeeded );
if (fRetval == FALSE) { dwLastError = GetLastError(); switch (dwLastError) { case ERROR_INSUFFICIENT_BUFFER: //
// Allocate more memory and try again.
//
dwBufAllocated = dwBufNeeded; pMem = (LPQUERY_SERVICE_CONFIG)AllocADsMem(dwBufAllocated); if (pMem == NULL) { hr = E_OUTOFMEMORY; break; }
fRetval = QueryServiceConfig(_schService, pMem, dwBufAllocated, &dwBufNeeded );
if (fRetval == FALSE) { WinNTCloseService();
hr = HRESULT_FROM_WIN32(GetLastError()); break; } break;
default: hr = HRESULT_FROM_WIN32(GetLastError()); break;
} if(FAILED(hr)){ WinNTCloseService(); goto cleanup; } }
WinNTCloseService();
//
// clear all properties from cache first if explicit GetInfo
//
if (fExplicit) { _pPropertyCache->flushpropcache(); }
if(pMem){ hr = UnMarshall(pMem, fExplicit); BAIL_IF_ERROR(hr); }else{ hr = UnMarshall((LPQUERY_SERVICE_CONFIG) FastConfigInfo, fExplicit); BAIL_IF_ERROR(hr); } cleanup: if(pMem) FreeADsMem(pMem); RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP CWinNTService::UnMarshall(THIS_ LPQUERY_SERVICE_CONFIG lpConfigInfo, BOOL fExplicit) { DWORD dwADsServiceType; DWORD dwADsStartType; DWORD dwADsErrorControl; HRESULT hr;
hr = SetLPTSTRPropertyInCache(_pPropertyCache, TEXT("Path"), lpConfigInfo->lpBinaryPathName, fExplicit );
hr = SetLPTSTRPropertyInCache(_pPropertyCache, TEXT("LoadOrderGroup"), lpConfigInfo->lpLoadOrderGroup, fExplicit );
hr = SetNulledStringPropertyInCache(_pPropertyCache, TEXT("Dependencies"), lpConfigInfo->lpDependencies, fExplicit );
hr = SetLPTSTRPropertyInCache(_pPropertyCache, TEXT("ServiceAccountName"), lpConfigInfo->lpServiceStartName, fExplicit );
hr = SetLPTSTRPropertyInCache(_pPropertyCache, TEXT("DisplayName"), lpConfigInfo->lpDisplayName, fExplicit );
//
// 0x133 is the bit mask for valid values of ADs ServiceTypes
//
dwADsServiceType = lpConfigInfo->dwServiceType & 0x133;
hr = SetDWORDPropertyInCache(_pPropertyCache, TEXT("ServiceType"), dwADsServiceType , fExplicit );
hr = SetDWORDPropertyInCache(_pPropertyCache, TEXT("StartType"), lpConfigInfo->dwStartType, fExplicit );
hr = SetDWORDPropertyInCache(_pPropertyCache, TEXT("ErrorControl"), lpConfigInfo->dwErrorControl, fExplicit );
hr = SetLPTSTRPropertyInCache( _pPropertyCache, TEXT("Name"), _Name, fExplicit );
RRETURN_EXP_IF_ERR(hr); }
//
// helper function WinNTAddService
//
HRESULT CWinNTService::WinNTAddService(void) { HRESULT hr = S_OK; SC_HANDLE schService = NULL; SC_HANDLE schSCManager = NULL; TCHAR szServerName[MAX_PATH]; BOOL fRetval; LPTSTR pszDisplayName = NULL; LPTSTR pszPath = NULL; LPTSTR pszLoadOrderGroup = NULL; DWORD dwServiceType; DWORD dwStartType; DWORD dwErrorControl;
hr = GetServerFromPath(_ADsPath,szServerName);
BAIL_IF_ERROR(hr);
//
// open the SCM for this server
//
schSCManager = OpenSCManager(szServerName, NULL, SC_MANAGER_ALL_ACCESS);
if(schSCManager == NULL){ hr = HRESULT_FROM_WIN32(GetLastError()); goto cleanup; }
hr = GetLPTSTRPropertyFromCache( _pPropertyCache, TEXT("DisplayName"), &pszDisplayName );
BAIL_IF_ERROR(hr);
hr = GetDWORDPropertyFromCache( _pPropertyCache, TEXT("ServiceType"), &dwServiceType );
BAIL_IF_ERROR(hr);
hr = GetDWORDPropertyFromCache( _pPropertyCache, TEXT("StartType"), &dwStartType );
BAIL_IF_ERROR(hr);
hr = GetDWORDPropertyFromCache( _pPropertyCache, TEXT("ErrorControl"), &dwErrorControl );
BAIL_IF_ERROR(hr);
hr = GetLPTSTRPropertyFromCache( _pPropertyCache, TEXT("Path"), &pszPath );
BAIL_IF_ERROR(hr);
schService = CreateService(schSCManager, _pszServiceName, pszDisplayName, SERVICE_ALL_ACCESS, dwServiceType, dwStartType, dwErrorControl, pszPath, NULL, NULL, NULL, NULL, NULL );
if(schService == NULL){ hr = HRESULT_FROM_WIN32(GetLastError()); goto cleanup; }
cleanup: if(schSCManager){ fRetval = CloseServiceHandle(schSCManager); if(!fRetval && SUCCEEDED(hr)){ RRETURN(HRESULT_FROM_WIN32(GetLastError())); } } if(schService){ fRetval = CloseServiceHandle(schService); if(!fRetval && SUCCEEDED(hr)){ RRETURN(HRESULT_FROM_WIN32(GetLastError())); } } if(pszDisplayName){ FreeADsStr(pszDisplayName); }
if(pszPath){ FreeADsStr(pszPath); }
if(pszLoadOrderGroup){ FreeADsStr(pszLoadOrderGroup); }
RRETURN(hr); }
STDMETHODIMP CWinNTService::get_HostComputer(THIS_ BSTR FAR* retval) { HRESULT hr; if(!retval){ RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER); } hr = ADsAllocString(_Parent, retval); RRETURN_EXP_IF_ERR(hr); }
STDMETHODIMP CWinNTService::put_HostComputer(THIS_ BSTR bstrHostComputer) { RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED); }
STDMETHODIMP CWinNTService::get_DisplayName(THIS_ BSTR FAR* retval) { GET_PROPERTY_BSTR((IADsService *)this, DisplayName); }
STDMETHODIMP CWinNTService::put_DisplayName(THIS_ BSTR bstrDisplayName) { PUT_PROPERTY_BSTR((IADsService *)this, DisplayName);
}
STDMETHODIMP CWinNTService::get_Version(THIS_ BSTR FAR* retval) { GET_PROPERTY_BSTR((IADsService *)this, Version);
}
STDMETHODIMP CWinNTService::put_Version(THIS_ BSTR bstrVersion) { PUT_PROPERTY_BSTR((IADsService *)this, Version); }
STDMETHODIMP CWinNTService::get_ServiceType(THIS_ long FAR* retval) { GET_PROPERTY_LONG((IADsService *)this, ServiceType); }
STDMETHODIMP CWinNTService::put_ServiceType(THIS_ long lServiceType) { PUT_PROPERTY_LONG((IADsService *)this, ServiceType); }
STDMETHODIMP CWinNTService::get_StartType(THIS_ LONG FAR* retval) { GET_PROPERTY_LONG((IADsService *)this, StartType); }
STDMETHODIMP CWinNTService::put_StartType(THIS_ LONG lStartType) { PUT_PROPERTY_LONG((IADsService *)this, StartType); }
STDMETHODIMP CWinNTService::get_Path(THIS_ BSTR FAR* retval) { GET_PROPERTY_BSTR((IADsService *)this, Path); }
STDMETHODIMP CWinNTService::put_Path(THIS_ BSTR bstrPath) {
PUT_PROPERTY_BSTR((IADsService *)this, Path); }
STDMETHODIMP CWinNTService::get_StartupParameters(THIS_ BSTR FAR* retval) { GET_PROPERTY_BSTR((IADsService *)this, StartupParameters);
}
STDMETHODIMP CWinNTService::put_StartupParameters(THIS_ BSTR bstrStartupParameters) { PUT_PROPERTY_BSTR((IADsService *)this, StartupParameters);
}
STDMETHODIMP CWinNTService::get_ErrorControl(THIS_ LONG FAR* retval) {
GET_PROPERTY_LONG((IADsService *)this, ErrorControl); }
STDMETHODIMP CWinNTService::put_ErrorControl(THIS_ LONG lErrorControl) { PUT_PROPERTY_LONG((IADsService *)this, ErrorControl); }
STDMETHODIMP CWinNTService::get_LoadOrderGroup(THIS_ BSTR FAR* retval) { GET_PROPERTY_BSTR((IADsService *)this, LoadOrderGroup);
}
STDMETHODIMP CWinNTService::put_LoadOrderGroup(THIS_ BSTR bstrLoadOrderGroup) {
PUT_PROPERTY_BSTR((IADsService *)this, LoadOrderGroup);
}
STDMETHODIMP CWinNTService::get_ServiceAccountName(THIS_ BSTR FAR* retval) { GET_PROPERTY_BSTR((IADsService *)this, ServiceAccountName);
}
STDMETHODIMP CWinNTService::put_ServiceAccountName(THIS_ BSTR bstrServiceAccountName) { RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED); }
STDMETHODIMP CWinNTService::get_ServiceAccountPath(THIS_ BSTR FAR* retval) { RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED); }
STDMETHODIMP CWinNTService::put_ServiceAccountPath(THIS_ BSTR bstrServiceAccountName) { RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED); }
STDMETHODIMP CWinNTService::get_Dependencies(THIS_ VARIANT FAR* retval) { GET_PROPERTY_VARIANT((IADsService *)this, Dependencies); }
STDMETHODIMP CWinNTService::put_Dependencies(THIS_ VARIANT vDependencies) { PUT_PROPERTY_VARIANT((IADsService *)this, Dependencies); }
STDMETHODIMP CWinNTService::SetPassword(THIS_ BSTR bstrNewPassword) {
//
// This routine should merely change password. Even if any other
// properties are set in the configuration functional set then they
// will not be touched.
// Therefore we do a QueryServiceConfig and get all the configuration
// related information, merely change the password and send it back.
// For this reason, it is not possible to reuse GetInfo or SetInfo
// because they change service config properties.
//
BOOL fRetval; LPQUERY_SERVICE_CONFIG pMem = NULL; HRESULT hr;
hr = WinNTOpenService(SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS, SERVICE_ALL_ACCESS);
BAIL_IF_ERROR(hr);
hr = GetServiceConfigInfo(&pMem); BAIL_IF_ERROR(hr);
//
// just change the field corresponding to password.
//
fRetval = ChangeServiceConfig(_schService, pMem->dwServiceType, pMem->dwStartType, pMem->dwErrorControl, pMem->lpBinaryPathName, pMem->lpLoadOrderGroup, NULL, pMem->lpDependencies, pMem->lpServiceStartName, (LPTSTR)bstrNewPassword, pMem->lpDisplayName );
if(!fRetval){ hr = HRESULT_FROM_WIN32(GetLastError()); goto cleanup; }
cleanup: if(pMem){ FreeADsMem(pMem); } WinNTCloseService(); RRETURN_EXP_IF_ERR(hr); }
//+---------------------------------------------------------------------------
//
// Function: CWinNTService::Start
//
// Synopsis: Attempts to start the service specified in _bstrServiceName on
// the server named in _bstrPath.
//
// Arguments:
//
// Returns: HRESULT.
//
// Modifies:
//
// History: 01/04/96 RamV Created
//
// Notes:
//----------------------------------------------------------------------------
STDMETHODIMP CWinNTService::Start(THIS) { HRESULT hr; hr = WinNTControlService(WINNT_START_SERVICE); RRETURN_EXP_IF_ERR(hr); }
//+---------------------------------------------------------------------------
//
// Function: CWinNTService::Stop
//
// Synopsis: Attempts to stop the service specified in _bstrServiceName on
// the server named in _bstrPath.
//
// Arguments:
//
// Returns: HRESULT.
//
// Modifies:
//
// History: 01/04/96 RamV Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CWinNTService::Stop(THIS) { HRESULT hr; hr = WinNTControlService(WINNT_STOP_SERVICE); RRETURN_EXP_IF_ERR(hr); }
//+---------------------------------------------------------------------------
//
// Function: CWinNTService::Pause
//
// Synopsis: Attempts to pause the service named _bstrServiceName on the
// server named in _bstrPath.
//
// Arguments:
//
// Returns: HRESULT.
//
// Modifies:
//
// History: 01-04-96 RamV Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CWinNTService::Pause(THIS) { HRESULT hr; hr = WinNTControlService(WINNT_PAUSE_SERVICE); RRETURN_EXP_IF_ERR(hr); }
//+---------------------------------------------------------------------------
//
// Function: CWinNTService::Continue
//
// Synopsis: Attempts to "unpause" the service specified in _bstrServiceName
// on the server named in _bstrPath.
//
// Arguments:
//
// Returns: HRESULT.
//
// Modifies:
//
// History: 01/04/96 RamV Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CWinNTService::Continue(THIS) { HRESULT hr; hr = WinNTControlService(WINNT_CONTINUE_SERVICE); RRETURN_EXP_IF_ERR(hr); }
//
// Helper Functions
//
HRESULT CWinNTService::GetServiceConfigInfo(LPQUERY_SERVICE_CONFIG *ppMem) { //
//gets the service configuration information into ppMem
//
BOOL fRetval; DWORD dwBufAllocated = 0; DWORD dwBufNeeded = 0; DWORD dwLastError; HRESULT hr = S_OK;
ADsAssert(ppMem); *ppMem = (LPQUERY_SERVICE_CONFIG)AllocADsMem(dwBufAllocated);
if (*ppMem == NULL){ hr = E_OUTOFMEMORY; goto cleanup; }
ADsAssert(_schService);
fRetval = QueryServiceConfig(_schService, (LPQUERY_SERVICE_CONFIG)(*ppMem), dwBufAllocated, &dwBufNeeded);
if (fRetval == FALSE) { dwLastError = GetLastError(); switch (dwLastError) { case ERROR_INSUFFICIENT_BUFFER: //
// Allocate more memory and try again.
//
FreeADsMem(*ppMem); *ppMem = NULL;
dwBufAllocated = dwBufNeeded; *ppMem = (LPQUERY_SERVICE_CONFIG)AllocADsMem(dwBufAllocated); if (*ppMem == NULL) { BAIL_IF_ERROR(hr = E_OUTOFMEMORY); }
fRetval = QueryServiceConfig(_schService, *ppMem, dwBufAllocated, &dwBufNeeded);
if (fRetval == FALSE) { hr = HRESULT_FROM_WIN32(GetLastError()); break; } break;
default: hr = HRESULT_FROM_WIN32(GetLastError()); break;
} BAIL_IF_ERROR(hr); }
if(*ppMem){ RRETURN(S_OK); }
cleanup: RRETURN(hr);
}
HRESULT CWinNTService::WinNTControlService( DWORD dwControl) { //
// abstracts out the common code of Start,Stop,Pause and Resume
//
HRESULT hr =S_OK, hrclose=S_OK, hrcontrol=S_OK; SERVICE_STATUS ssStatusInfo; BOOL fRetval;
if(_fValidHandle){ //
// an open handle exists, blow it away
//
hrclose = WinNTCloseService(); BAIL_ON_FAILURE(hrclose); _fValidHandle = FALSE; }
hr = WinNTOpenService(SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS, GENERIC_EXECUTE| SERVICE_INTERROGATE );
BAIL_ON_FAILURE(hr);
_fValidHandle = TRUE;
switch(dwControl){
case WINNT_START_SERVICE: fRetval = StartService(_schService, 0, NULL );
if(!fRetval){ hrcontrol = HRESULT_FROM_WIN32(GetLastError()); goto error; } _dwOpPending = PENDING_START; break;
case WINNT_STOP_SERVICE: fRetval = ControlService(_schService, SERVICE_CONTROL_STOP, &ssStatusInfo);
if(!fRetval){ hrcontrol = HRESULT_FROM_WIN32(GetLastError()); goto error; } _dwOpPending = PENDING_STOP; break;
case WINNT_PAUSE_SERVICE: fRetval = ControlService(_schService, SERVICE_CONTROL_PAUSE, &ssStatusInfo);
if(!fRetval){ hrcontrol = HRESULT_FROM_WIN32(GetLastError()); goto error; } _dwOpPending = PENDING_PAUSE; break;
case WINNT_CONTINUE_SERVICE: fRetval = ControlService(_schService, SERVICE_CONTROL_CONTINUE, &ssStatusInfo);
if(!fRetval){ hrcontrol = HRESULT_FROM_WIN32(GetLastError()); goto error; } _dwOpPending = PENDING_CONTINUE; break;
default: hrcontrol = E_FAIL; goto error; } _dwTimeStarted = GetTickCount(); _dwWaitHint = 10000; //10 seconds
_dwCheckPoint = 0;
RRETURN(S_OK);
error: if(FAILED(hrcontrol)){ _fValidHandle = FALSE; RRETURN(hrcontrol); } else if(FAILED(hrclose)){ RRETURN(hrclose); } else{ RRETURN(hr); } }
//+---------------------------------------------------------------------------
//
// Function: CWinNTService::WinNTOpenService
//
// Synopsis: Opens the Service Control Manager on the machine specified in
// _bstrPath, then opens the Service specified in _bstrServiceName.
// The handle to the SCM is placed in _schSCManager, and the
// handle to the service is placed in _schService.
//
// Arguments: [dwSCMDesiredAccess] -- type of SCM access needed
// [dwSvrDesiredAccess] -- type of Service access required
//
// Returns: HRESULT.
//
// Modifies:
//
// History: 03-17-95 t-skwan Created
// 01/04/96 RamV Modified
//
//----------------------------------------------------------------------------
HRESULT CWinNTService::WinNTOpenService( DWORD dwSCMDesiredAccess, DWORD dwSvrDesiredAccess ) { HRESULT hr; DWORD dwLastError;
//
// Open the Service Control Manager.
//
//
// OpenSCManager(
// LPCTSTR lpszMachineName,
// LPCTSTR lpszDatabaseName.
// DWORD fdwDesiredAccess)
//
_schSCManager = OpenSCManager(_pszServerName, NULL, dwSCMDesiredAccess);
if (_schSCManager == NULL) {
dwLastError = GetLastError(); hr = HRESULT_FROM_WIN32(dwLastError); RRETURN(hr); }
//
// Get a handle to the specified service.
//
_schService = OpenService(_schSCManager, _pszServiceName, dwSvrDesiredAccess);
if(_schService == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); CloseServiceHandle(_schSCManager); _schSCManager = NULL; RRETURN(hr); }
RRETURN(S_OK); }
//+---------------------------------------------------------------------------
//
// Function: CWinNTService::WinNTCloseService
//
// Synopsis: Closes the Service handle and the Service Control Manager
// handle.
//
// Arguments:
//
// Returns: HRESULT.
//
// Modifies:
//
// History: 03-17-95 t-skwan Created
// 01/04/96 RamV Modified
//
//----------------------------------------------------------------------------
HRESULT CWinNTService::WinNTCloseService() { BOOL fRetval = TRUE;
//
// Close the Service handle.
//
if(_schService){ fRetval = CloseServiceHandle(_schService); _schService = NULL; }
if (!fRetval) { //
// Ack. What do we do if there is an error closing a service?
//
RRETURN(HRESULT_FROM_WIN32(GetLastError())); }
//
// Close the Service Control Manager.
//
if(_schSCManager){ fRetval = CloseServiceHandle(_schSCManager); _schSCManager = NULL; } if (!fRetval) { //
// Ack. What do we do if there is an error closing an SCM?
//
RRETURN(HRESULT_FROM_WIN32(GetLastError())); }
RRETURN(S_OK); }
STDMETHODIMP CWinNTService::get_Status(THIS_ long FAR* plStatusCode) { HRESULT hr = S_OK; BOOL fRetval = FALSE, found = FALSE; SERVICE_STATUS Status; DWORD dwStatus = 0;
if(plStatusCode == NULL){ RRETURN_EXP_IF_ERR(E_POINTER); }
*plStatusCode = -1; //-1 is an invalid code
if(!(_fValidHandle)){
//
// currently not waiting on any service
//
hr = WinNTOpenService(SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS, GENERIC_EXECUTE|SERVICE_INTERROGATE);
BAIL_IF_ERROR(hr);
fRetval = ControlService(_schService, SERVICE_CONTROL_INTERROGATE, &Status);
if(!fRetval){ hr = HRESULT_FROM_WIN32(GetLastError()); if(hr == HRESULT_FROM_WIN32(ERROR_SERVICE_NOT_ACTIVE)){ dwStatus = SERVICE_STOPPED; hr = S_OK; } goto cleanup; }
dwStatus = Status.dwCurrentState;
hr = WinNTCloseService();
goto cleanup;
}
//
// if you are here
// you are waiting for a service to complete
//
//
// NOTE: QueryServiceStatus queries the SCM rather than
// the service directly so to get a more upto date answer
// we need to use control service with interrogate option
//
hr = WinNTOpenService(SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS, GENERIC_EXECUTE|SERVICE_INTERROGATE);
BAIL_IF_ERROR(hr);
fRetval = ControlService(_schService, SERVICE_CONTROL_INTERROGATE, &Status);
if(!fRetval){ hr = HRESULT_FROM_WIN32(GetLastError()); if(hr == HRESULT_FROM_WIN32(ERROR_SERVICE_NOT_ACTIVE)){ dwStatus = SERVICE_STOPPED; hr = S_OK; } goto cleanup; }
hr = EvalPendingOperation(PENDING_START, SERVICE_RUNNING, SERVICE_START_PENDING, &Status, &dwStatus );
BAIL_IF_ERROR(hr);
if(dwStatus != 0){ //
// the correct scenario was found
//
goto cleanup; } hr = EvalPendingOperation(PENDING_STOP, SERVICE_STOPPED, SERVICE_STOP_PENDING, &Status, &dwStatus );
BAIL_IF_ERROR(hr);
if(dwStatus != 0){ //
// the correct scenario was found
//
goto cleanup; }
hr = EvalPendingOperation(PENDING_PAUSE, SERVICE_PAUSED, SERVICE_PAUSE_PENDING, &Status, &dwStatus );
BAIL_IF_ERROR(hr);
if(dwStatus != 0){ //
// the correct scenario was found
//
goto cleanup; }
hr = EvalPendingOperation(PENDING_CONTINUE, SERVICE_RUNNING, SERVICE_CONTINUE_PENDING, &Status, &dwStatus );
BAIL_IF_ERROR(hr);
ADsAssert(dwStatus != 0); //we must find the appropriate scenario
cleanup: if(SUCCEEDED(hr)){ //
// instead of a conversion routine, we return WinNT Status Code
//
*plStatusCode = dwStatus;
} RRETURN_EXP_IF_ERR(hr); }
HRESULT CWinNTService::EvalPendingOperation( THIS_ DWORD dwOpPending, DWORD dwStatusDone, DWORD dwStatusPending, LPSERVICE_STATUS pStatus, DWORD *pdwRetval )
{
DWORD dwCurrentStatus; BOOL fRetval; HRESULT hr =S_OK; DWORD dwNow;
dwCurrentStatus = pStatus->dwCurrentState;
if(_dwOpPending == dwOpPending){
if(dwCurrentStatus == dwStatusDone){ //
//was pending, is now completed
//
_dwOpPending = NOTPENDING; *pdwRetval = dwStatusDone; hr = WinNTCloseService(); BAIL_ON_FAILURE(hr); _fValidHandle = FALSE; RRETURN(S_OK);
} else if(dwCurrentStatus = dwStatusPending){ //
//see if progress has been made since the last time we checked
//
if(pStatus->dwCheckPoint !=_dwCheckPoint){ //
// progress was made
//
*pdwRetval = dwStatusPending; _dwCheckPoint = pStatus->dwCheckPoint; _dwWaitHint = pStatus->dwWaitHint; _dwTimeStarted = GetTickCount(); RRETURN(S_OK); }
dwNow = GetTickCount();
if(2*_dwWaitHint < TickCountDiff(dwNow,_dwTimeStarted)){ //
// you can still wait
//
*pdwRetval = dwStatusPending; RRETURN(S_OK); }
else{
//
// took too long without signs of progress
//
*pdwRetval = SERVICE_ERROR; _dwOpPending = NOTPENDING; hr = WinNTCloseService(); BAIL_ON_FAILURE(hr); _fValidHandle = FALSE; RRETURN(S_OK); } } else{
//
// an operation is pending but we arent going anywhere
// recover gracefully
//
_dwOpPending = NOTPENDING; hr = WinNTCloseService(); BAIL_ON_FAILURE(hr); _fValidHandle = FALSE; *pdwRetval = SERVICE_ERROR; RRETURN(S_OK); }
} error: RRETURN(hr); }
|