///////////////////////////////////////////////////////////////////// // // 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 = AllocBstr(PVD_CLASS_SERVER); if ( !ClassName ) { return WBEM_E_OUT_OF_MEMORY; } 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 + 40 ]; 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 + 40 ]; 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; };