windows-nt/Source/XPSP1/NT/ds/dns/server/wmi/source/server.cpp
2020-09-26 16:20:57 +08:00

607 lines
15 KiB
C++

/////////////////////////////////////////////////////////////////////
//
// CopyRight ( c ) 1999 Microsoft Corporation
//
// Module Name: server.cpp
//
// Description:
// Implementation of CDnsserver class
//
// Author:
// Henry Wang ( henrywa ) March 8, 2000
//
//
//////////////////////////////////////////////////////////////////////
#include "DnsWmi.h"
/////////////////////////////////////////////////////////////////////////////
//++
//
// Description:
// execute methods defined for dns server class in the mof
//
// Arguments:
// ObjPath [IN] pointing to the object that the
// method should be performed on
// wzMethodName [IN] name of the method to be invoked
// lFlags [IN] WMI flag
// pInParams [IN] Input parameters for the method
// pHandler [IN] WMI sink pointer
//
// Return Value:
// WBEM_S_NO_ERROR
// WBEM_E_INVALID_PARAMETER
//
//--
/////////////////////////////////////////////////////////////////////////////
SCODE
CDnsServer::ExecuteMethod(
CObjPath & ObjPath,
WCHAR * wzMethodName,
long lFlag,
IWbemClassObject * pInArgs,
IWbemObjectSink * pHandler)
{
CDnsWrap& dns = CDnsWrap::DnsObject();
#if 0
//
// Restart is so totally broken I'm not going to expose it.
//
if(_wcsicmp( wzMethodName, PVD_MTH_SRV_RESTART) == 0)
{
wstring wstrServer = ObjPath.GetStringValueForProperty(
PVD_SRV_SERVER_NAME );
int rt = dns.dnsRestartServer((WCHAR*)wstrServer.data());
if( rt != ERROR_SUCCESS)
{
return WBEM_E_FAILED;
}
}
else
#endif
if(_wcsicmp( wzMethodName, PVD_MTH_SRV_START_SERVICE) == 0)
{
return StartServer();
}
else if(_wcsicmp( wzMethodName, PVD_MTH_SRV_STOP_SERVICE) == 0)
{
return StopServer();
}
else if(_wcsicmp(
wzMethodName,
PVD_MTH_ZONE_GETDISTINGUISHEDNAME) == 0)
{
wstring wstrName ;
CWbemClassObject OutParams, OutClass, Class ;
HRESULT hr;
dns.dnsDsServerName(wstrName);
BSTR ClassName=NULL;
ClassName = AllocBstr(PVD_CLASS_SERVER);
hr = m_pNamespace->GetObject(ClassName, 0, 0, &Class, NULL);
SysFreeString(ClassName);
if ( SUCCEEDED ( hr ) )
{
Class.GetMethod(wzMethodName, 0, NULL, &OutClass);
OutClass.SpawnInstance(0, &OutParams);
OutParams.SetProperty(wstrName, PVD_DNS_RETURN_VALUE);
hr = pHandler->Indicate(1, &OutParams);
}
return hr;
}
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// Description:
// retrieve record object pointed by the given object path
//
// Arguments:
// ObjectPath [IN] object path to object
// lFlags [IN] WMI flag
// pCtx [IN] WMI context
// pHandler [IN] WMI sink pointer
//
// Return Value:
// WBEM_S_NO_ERROR
//
//--
/////////////////////////////////////////////////////////////////////////////
SCODE
CDnsServer::GetObject(
CObjPath & ObjectPath,
long lFlags,
IWbemContext * pCtx,
IWbemObjectSink * pHandler
)
{
SCODE sc;
CWbemClassObject NewInst;
sc = m_pClass->SpawnInstance(0, &NewInst);
if(FAILED(sc))
{
return sc;
}
wstring wstrServerName = ObjectPath.GetStringValueForProperty(
PVD_SRV_SERVER_NAME );
if ( wstrServerName.empty())
{
return WBEM_E_FAILED;
}
SC_HANDLE schService = NULL;
SC_HANDLE schSCManager = NULL;
LPQUERY_SERVICE_CONFIG lpServiceConfig = NULL;
DWORD cbBufSize;
DWORD BytesNeeded;
SERVICE_STATUS ServiceStatus;
try
{
if ((schSCManager = OpenSCManager (
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_ALL_ACCESS))==NULL) // access required
{
throw GetLastError();
}
if ((schService = OpenService(
schSCManager,
"DNS",
SERVICE_ALL_ACCESS))==NULL)
{
throw GetLastError();
}
if (QueryServiceConfig(
schService, // handle to service
lpServiceConfig,
0, // size of structure
&cbBufSize // bytes needed
) == FALSE)
{
lpServiceConfig =
(LPQUERY_SERVICE_CONFIG) new BYTE[cbBufSize];
if ( !lpServiceConfig)
{
throw ( ERROR_OUTOFMEMORY );
}
if(QueryServiceConfig(
schService, // handle to service
lpServiceConfig,
cbBufSize, // size of structure
&BytesNeeded // bytes needed
) == FALSE)
throw GetLastError();
wstring wstrStartMode;
switch(lpServiceConfig->dwStartType)
{
case SERVICE_DEMAND_START:
wstrStartMode = L"Manual";
break;
default:
wstrStartMode = L"Automatic";
break;
}
NewInst.SetProperty(
wstrStartMode,
PVD_SRV_STARTMODE);
if(QueryServiceStatus(
schService, // handle to service
&ServiceStatus // pointer to service status structure
) == FALSE)
{
throw GetLastError();
}
DWORD dwStatus;
switch(ServiceStatus.dwCurrentState)
{
case SERVICE_RUNNING:
dwStatus = 1;
break;
default:
dwStatus = 0;
}
NewInst.SetProperty(
dwStatus,
PVD_SRV_STARTED);
}
CDnsWrap& dns = CDnsWrap::DnsObject();
NewInst.SetProperty(
dns.GetServerName(),
PVD_SRV_SERVER_NAME);
dns.dnsServerPropertyGet(
NewInst,
TRUE);
}
catch(DWORD dwError)
{
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
delete [] lpServiceConfig;
}
catch(CDnsProvException e)
{
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
delete [] lpServiceConfig;
lpServiceConfig=NULL;
// if server not running, we still want to
//return an instance, so user can call start service
//
if(_stricmp(e.what(), "RPC_S_SERVER_UNAVAILABLE") != 0)
{
throw e;
}
}
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
delete [] lpServiceConfig;
pHandler->Indicate(1,&NewInst);
return sc;
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// Description:
// enum instances of dns server
//
// Arguments:
// lFlags [IN] WMI flag
// pCtx [IN] WMI context
// pHandler [IN] WMI sink pointer
//
// Return Value:
// WBEM_S_NO_ERROR
//
//--
/////////////////////////////////////////////////////////////////////////////
SCODE
CDnsServer::EnumInstance(
long lFlags,
IWbemContext * pCtx,
IWbemObjectSink * pHandler
)
{
// there is only one instance
CObjPath ObjPath;
ObjPath.SetClass(PVD_CLASS_SERVER);
ObjPath.AddProperty(
PVD_SRV_SERVER_NAME,
PVD_DNS_LOCAL_SERVER);
return GetObject(ObjPath, lFlags,pCtx,pHandler);
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDnsServer::CDnsServer()
{
}
CDnsServer::CDnsServer(
const WCHAR* wszName,
CWbemServices *pNamespace)
:CDnsBase(wszName, pNamespace)
{
}
CDnsServer::~CDnsServer()
{
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// Description:
// create an instance of CDnsServer
//
// Arguments:
// wszName [IN] class name
// pNamespace [IN] wmi namespace
// szType [IN] child class name of resource record class
//
// Return Value:
// WBEM_S_NO_ERROR
//
//--
/////////////////////////////////////////////////////////////////////////////
CDnsBase*
CDnsServer::CreateThis(
const WCHAR * wszName,
CWbemServices * pNamespace,
const char * szType
)
{
return new CDnsServer(wszName, pNamespace);
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// Description:
// start dns server
//
// Arguments:
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
SCODE
CDnsServer::StartServer()
{
SC_HANDLE schService = NULL;
SC_HANDLE schSCManager = NULL;
try
{
if ((schSCManager = OpenSCManager (
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_ALL_ACCESS))==NULL) // access required
{
throw GetLastError();
}
if ((schService = OpenService(
schSCManager,
"DNS",
SERVICE_ALL_ACCESS))==NULL)
{
throw GetLastError();
}
// make sure database is not locked
QUERY_SERVICE_LOCK_STATUS qsls;
DWORD dwbBytesNeeded, dwRet=1;
while(dwRet)
{
if(!QueryServiceLockStatus(
schSCManager,
&qsls,
sizeof(qsls)+2,
&dwbBytesNeeded))
{
throw GetLastError();
}
if( (dwRet = qsls.fIsLocked) > 0)
{
Sleep(2000);
}
}
if (StartService(
schService,
0,
NULL)==FALSE)
{
throw GetLastError();
}
DWORD dwTimeOut=6000; // 6 sec
DWORD dwTimeCount=0;
while ( dwTimeCount < dwTimeOut)
{
SERVICE_STATUS ServiceStatus;
if(QueryServiceStatus(
schService, // handle to service
&ServiceStatus // pointer to service status structure
) == FALSE)
{
throw GetLastError();
}
if(ServiceStatus.dwCurrentState != SERVICE_RUNNING)
{
Sleep(2000);
dwTimeCount +=2000;
}
else
{
break;
}
}
}
catch(DWORD dwError)
{
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
CHAR szErrDesc[MAX_PATH];
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
szErrDesc,
MAX_PATH,
NULL
);
CHAR szErr[MAX_PATH];
strcpy(szErr, "Fail to start Dns because ");
strcat(szErr, szErrDesc);
CDnsProvException e(szErr);
throw e;
}
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// Description:
// stop dns server
//
// Arguments:
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
SCODE
CDnsServer::StopServer()
{
SERVICE_STATUS ss;
SC_HANDLE schService = NULL;
SC_HANDLE schSCManager = NULL;
try
{
if ((schSCManager = OpenSCManager (
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_ALL_ACCESS))==NULL) // access required
{
throw GetLastError();
}
if ((schService = OpenService(
schSCManager,
"DNS",
SERVICE_ALL_ACCESS))==NULL)
{
throw GetLastError();
}
if (ControlService(
schService,
SERVICE_CONTROL_STOP,
(LPSERVICE_STATUS)&ss) == FALSE)
{
throw GetLastError();
}
// check its state
DWORD dwTimeOut=6000; // 6 sec
DWORD dwTimeCount=0;
while ( dwTimeCount < dwTimeOut)
{
SERVICE_STATUS ServiceStatus;
if(QueryServiceStatus(
schService, // handle to service
&ServiceStatus // pointer to service status structure
) == FALSE)
{
throw GetLastError();
}
if(ServiceStatus.dwCurrentState != SERVICE_STOPPED)
{
Sleep(2000);
dwTimeCount +=2000;
}
else
break;
}
}
catch(DWORD dwError)
{
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
CHAR szErrDesc[MAX_PATH];
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
szErrDesc,
MAX_PATH,
NULL
);
CHAR szErr[MAX_PATH];
strcpy(szErr, "Fail to stop Dns because ");
strcat(szErr, szErrDesc);
CDnsProvException e(szErr);
throw e;
}
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return WBEM_S_NO_ERROR;
}
/////////////////////////////////////////////////////////////////////////////
//++
//
// Description:
// save this instance
//
// Arguments:
// InstToPut [IN] WMI object to be saved
// lFlags [IN] WMI flag
// pCtx [IN] WMI context
// pHandler [IN] WMI sink pointer
//
// Return Value:
//
//
//--
/////////////////////////////////////////////////////////////////////////////
SCODE
CDnsServer::PutInstance(
IWbemClassObject * pInst ,
long lFlags,
IWbemContext* pCtx ,
IWbemObjectSink * pHandler
)
{
DBG_FN( "CDnsServer::PutInstance" )
DNS_DEBUG( INSTPROV, (
"%s: pInst=%p\n", fn, pInst ));
CDnsWrap& dns = CDnsWrap::DnsObject();
CWbemClassObject Inst(pInst);
dns.dnsServerPropertySet(
Inst,
FALSE);
return S_OK;
};