594 lines
16 KiB
C++
594 lines
16 KiB
C++
|
/*---------------------------------------------------------------------------
|
||
|
File: AgentRpc.cpp
|
||
|
|
||
|
Comments: RPC interface for DCT Agent service
|
||
|
|
||
|
(c) Copyright 1999, Mission Critical Software, Inc., All Rights Reserved
|
||
|
Proprietary and confidential to Mission Critical Software, Inc.
|
||
|
|
||
|
REVISION LOG ENTRY
|
||
|
Revision By: Christy Boles
|
||
|
Revised on 02/19/99 11:39:58
|
||
|
|
||
|
---------------------------------------------------------------------------
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <objbase.h>
|
||
|
|
||
|
#include "AgSvc.h"
|
||
|
|
||
|
#include "Common.hpp"
|
||
|
#include "UString.hpp"
|
||
|
#include "Err.hpp"
|
||
|
#include "TEvent.hpp"
|
||
|
#include "EaLen.hpp"
|
||
|
#include "Cipher.hpp"
|
||
|
#include "IsAdmin.hpp"
|
||
|
#include "ResStr.h"
|
||
|
|
||
|
//#import "\bin\McsVarSetMin.tlb" no_namespace, named_guids
|
||
|
//#import "\bin\MCSEADCTAgent.tlb" no_namespace, named_guids
|
||
|
#import "VarSet.tlb" no_namespace, named_guids rename("property", "aproperty")
|
||
|
#import "Engine.tlb" no_namespace, named_guids
|
||
|
|
||
|
#include "TNode.hpp"
|
||
|
|
||
|
#ifdef OFA
|
||
|
#include "atlbase.h"
|
||
|
#endif
|
||
|
|
||
|
extern LPSTREAM pStream;
|
||
|
extern TErrorEventLog err;
|
||
|
extern BOOL gSuicide;
|
||
|
extern BOOL gDebug;
|
||
|
extern BOOL gLocallyInstalled;
|
||
|
extern BOOL gbFinished;
|
||
|
extern BOOL gbIsNt351;
|
||
|
extern StringLoader gString;
|
||
|
|
||
|
DWORD RemoveService();
|
||
|
DWORD UnregisterFiles();
|
||
|
DWORD RemoveFiles();
|
||
|
DWORD RegisterDLL(const WCHAR * filename);
|
||
|
DWORD RegisterExe(const WCHAR * filename);
|
||
|
BOOL IsLocallyInstalled();
|
||
|
|
||
|
DWORD __stdcall
|
||
|
ShutdownService(
|
||
|
/* [in] */ DWORD bFlags
|
||
|
);
|
||
|
|
||
|
|
||
|
|
||
|
TNodeList gJobList;
|
||
|
|
||
|
class TJobNode : public TNode
|
||
|
{
|
||
|
WCHAR guid[LEN_Guid];
|
||
|
public:
|
||
|
TJobNode(WCHAR const * id) { safecopy(guid,id); }
|
||
|
WCHAR const * JobID() { return guid; }
|
||
|
};
|
||
|
|
||
|
// thread entry point, waits for the specified job to end,
|
||
|
// then shuts down the DCTAgentService
|
||
|
DWORD __stdcall
|
||
|
MonitorJob(
|
||
|
void * arg // in - BSTR job ID
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = CoInitialize(NULL);
|
||
|
_bstr_t jobID = (BSTR)arg;
|
||
|
IDCTAgent * pLocalAgent = NULL;
|
||
|
BOOL bDone = FALSE;
|
||
|
|
||
|
try {
|
||
|
// Get a pointer to the local agent
|
||
|
if ( SUCCEEDED(hr) )
|
||
|
{
|
||
|
hr = CoUnmarshalInterface( pStream, IID_IDCTAgent,(void**)&pLocalAgent);
|
||
|
if ( SUCCEEDED(hr) )
|
||
|
{
|
||
|
// Reset the stream to the beginning
|
||
|
LARGE_INTEGER offset = { 0,0 };
|
||
|
ULARGE_INTEGER result = { 0,0 };
|
||
|
|
||
|
hr = pStream->Seek(offset,STREAM_SEEK_SET,&result);
|
||
|
|
||
|
}
|
||
|
|
||
|
// Get the status of the job
|
||
|
IUnknown * pUnk = NULL;
|
||
|
|
||
|
if ( SUCCEEDED(hr) )
|
||
|
{
|
||
|
do {
|
||
|
hr = pLocalAgent->raw_QueryJobStatus(jobID,&pUnk);
|
||
|
if ( SUCCEEDED(hr) )
|
||
|
{
|
||
|
IVarSetPtr pVarSet = pUnk;
|
||
|
_bstr_t status = pVarSet->get(GET_BSTR(DCTVS_JobStatus));
|
||
|
|
||
|
if ( gDebug )
|
||
|
{
|
||
|
//* err.DbgMsgWrite(0,L"Monitoring job %ls, Status: %ls",(WCHAR*)jobID, (WCHAR*)status);
|
||
|
err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_MONJOBSTAT),(WCHAR*)jobID, (WCHAR*)status);
|
||
|
}
|
||
|
if ( ! UStrICmp(status,GET_STRING(IDS_DCT_Status_Completed)) )
|
||
|
{
|
||
|
bDone = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
pUnk->Release();
|
||
|
pUnk = NULL;
|
||
|
Sleep(60*1000); // one minute
|
||
|
}
|
||
|
while ( SUCCEEDED(hr) );
|
||
|
// int x = pLocalAgent->Release();
|
||
|
pLocalAgent->Release();
|
||
|
}
|
||
|
|
||
|
// TODO: make this an option
|
||
|
if ( bDone )
|
||
|
{
|
||
|
hr = ShutdownService(0);
|
||
|
}
|
||
|
CoUninitialize();
|
||
|
}
|
||
|
}
|
||
|
catch ( ... )
|
||
|
{
|
||
|
//* err.DbgMsgWrite(0,L"An exception occurred while monitoring the job. Shutting down the agent service.");
|
||
|
err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_MONERROR));
|
||
|
try {
|
||
|
pLocalAgent->Release();
|
||
|
}
|
||
|
catch ( ... )
|
||
|
{
|
||
|
}
|
||
|
}
|
||
|
if ( gDebug )
|
||
|
//* err.DbgMsgWrite(0,L"MonitorJob exiting, hr = %lx",hr);
|
||
|
err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_MONEXIT),hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
AuthenticateClient(
|
||
|
handle_t hBinding // in - binding for client call
|
||
|
)
|
||
|
{
|
||
|
DWORD rc;
|
||
|
|
||
|
rc = RpcImpersonateClient(hBinding);
|
||
|
if ( rc )
|
||
|
{
|
||
|
err.SysMsgWrite(ErrE,rc,DCT_MSG_FAILED_TO_IMPERSONATE_D,rc);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
rc = IsAdminLocal();
|
||
|
if ( rc )
|
||
|
{
|
||
|
err.SysMsgWrite(ErrE,rc,DCT_MSG_CLIENT_NOT_ADMIN_D, rc);
|
||
|
}
|
||
|
|
||
|
RpcRevertToSelf();
|
||
|
}
|
||
|
return rc;
|
||
|
}
|
||
|
DWORD
|
||
|
RegisterPlugInFiles(
|
||
|
IVarSet * pVarSet
|
||
|
)
|
||
|
{
|
||
|
DWORD rc = 0;
|
||
|
WCHAR key[MAX_PATH + 50];
|
||
|
int nFiles = 0;
|
||
|
_bstr_t filename;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if ( gDebug )
|
||
|
//* err.DbgMsgWrite(0,L"Starting plug-in file registration.");
|
||
|
err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_STARTPLUGREG));
|
||
|
|
||
|
swprintf(key,GET_STRING(IDS_DCTVSFmt_PlugIn_RegisterFiles_D),nFiles);
|
||
|
filename = pVarSet->get(key);
|
||
|
|
||
|
if ( filename.length() != 0 )
|
||
|
{
|
||
|
if ( gDebug )
|
||
|
//* err.DbgMsgWrite(0,L"File %ld = %ls",nFiles,(WCHAR*)filename);
|
||
|
err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_FILEREG),nFiles,(WCHAR*)filename);
|
||
|
|
||
|
if ( !UStrICmp((WCHAR *)filename + filename.length() - 4,L".DLL") )
|
||
|
{
|
||
|
RegisterDLL(filename);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
RegisterExe(filename);
|
||
|
}
|
||
|
nFiles++;
|
||
|
}
|
||
|
|
||
|
} while (filename.length() != 0);
|
||
|
if ( gDebug )
|
||
|
//* err.DbgMsgWrite(0,L"Done Registering plug-in files.");
|
||
|
err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_PLUGREGDONE));
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
DWORD __stdcall
|
||
|
EaxsSubmitJob(
|
||
|
/* [in] */ handle_t hBinding,
|
||
|
/* [string][in] */ const WCHAR __RPC_FAR *filename,
|
||
|
/* [string][in] */ const WCHAR __RPC_FAR *extra,
|
||
|
/* [size_is][string][out] */ WCHAR __RPC_FAR *jobGUID
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = 0;
|
||
|
WCHAR filenameW[MAX_PATH];
|
||
|
WCHAR pathW[MAX_PATH];
|
||
|
IDCTAgent * pLocalAgent = NULL;
|
||
|
// BOOL bFileCopied = FALSE;
|
||
|
BOOL gbDeleteOnCompletion = FALSE;
|
||
|
|
||
|
// Make sure the client is an admin on the local machine, otherwise, forget it
|
||
|
hr = AuthenticateClient(hBinding);
|
||
|
if ( hr )
|
||
|
{
|
||
|
return hr;
|
||
|
}
|
||
|
hr = CoInitialize(NULL);
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
err.SysMsgWrite(ErrE,hr,DCT_MSG_COINITIALIZE_FAILED_D,hr);
|
||
|
return hr;
|
||
|
}
|
||
|
safecopy(filenameW,filename);
|
||
|
|
||
|
// get the path for our install directory
|
||
|
if ( ! GetModuleFileName(NULL,pathW,DIM(pathW)) )
|
||
|
{
|
||
|
hr = GetLastError();
|
||
|
safecopy(pathW,filenameW);
|
||
|
err.SysMsgWrite(ErrW,hr,DCT_MSG_GET_MODULE_PATH_FAILED_D,hr);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
UStrCpy(pathW + UStrLen(pathW) - UStrLen(GET_STRING(IDS_SERVICE_EXE)),filenameW, DIM(pathW));
|
||
|
}
|
||
|
|
||
|
|
||
|
hr = CoUnmarshalInterface( pStream, IID_IDCTAgent,(void**)&pLocalAgent);
|
||
|
// interface pointer requested in riid);
|
||
|
if ( SUCCEEDED(hr) )
|
||
|
{
|
||
|
// Reset the stream to the beginning
|
||
|
LARGE_INTEGER offset = { 0,0 };
|
||
|
ULARGE_INTEGER result = { 0,0 };
|
||
|
|
||
|
hr = pStream->Seek(offset,STREAM_SEEK_SET,&result);
|
||
|
|
||
|
BSTR jobID = NULL;
|
||
|
|
||
|
// Read the varset data from the file
|
||
|
|
||
|
IVarSetPtr pVarSet;
|
||
|
IStoragePtr store = NULL;
|
||
|
|
||
|
// Try to create the COM objects
|
||
|
hr = pVarSet.CreateInstance(CLSID_VarSet);
|
||
|
if ( SUCCEEDED(hr) )
|
||
|
{
|
||
|
|
||
|
// Read the VarSet from the data file
|
||
|
hr = StgOpenStorage(pathW,NULL,STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,NULL,0,&store);
|
||
|
if ( SUCCEEDED(hr) )
|
||
|
{
|
||
|
// Load the data into a new varset
|
||
|
hr = OleLoad(store,IID_IUnknown,NULL,(void **)&pVarSet);
|
||
|
if ( SUCCEEDED(hr) )
|
||
|
{
|
||
|
_bstr_t text = pVarSet->get(GET_BSTR(DCTVS_Options_DeleteFileAfterLoad));
|
||
|
|
||
|
if ( !UStrICmp(text,GET_STRING(IDS_YES)) )
|
||
|
{
|
||
|
// Free the storage pointer to the file
|
||
|
store = NULL;
|
||
|
if ( DeleteFile(pathW) )
|
||
|
{
|
||
|
if ( gDebug )
|
||
|
//* err.DbgMsgWrite(0,L"Deleted job file %ls",pathW);
|
||
|
err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_JOBDEL),pathW);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
err.SysMsgWrite(ErrW,GetLastError(),DCT_MSG_JOB_FILE_NOT_DELETED_SD,pathW,GetLastError());
|
||
|
}
|
||
|
}
|
||
|
text = pVarSet->get(GET_BSTR(DCTVS_Options_RemoveAgentOnCompletion));
|
||
|
if ( !UStrICmp(text,GET_STRING(IDS_YES)))
|
||
|
{
|
||
|
gbDeleteOnCompletion = TRUE;
|
||
|
}
|
||
|
text = pVarSet->get(GET_BSTR(DCTVS_AgentService_DebugMode));
|
||
|
if ( !UStrICmp(text,GET_STRING(IDS_YES)))
|
||
|
{
|
||
|
gDebug = TRUE;
|
||
|
}
|
||
|
WCHAR password[LEN_Password];
|
||
|
safecopy(password,extra);
|
||
|
|
||
|
|
||
|
#ifdef OFA
|
||
|
if(!IsLocallyInstalled())
|
||
|
#endif
|
||
|
RegisterPlugInFiles(pVarSet);
|
||
|
|
||
|
pVarSet->put(GET_BSTR(DCTVS_Options_Credentials_Password),password);
|
||
|
|
||
|
hr = pLocalAgent->raw_SubmitJob(pVarSet,&jobID);
|
||
|
if ( SUCCEEDED(hr))
|
||
|
{
|
||
|
TJobNode * pnode = new TJobNode(jobID);
|
||
|
gJobList.InsertBottom(pnode);
|
||
|
err.MsgWrite(0,DCT_MSG_AGENT_JOB_STARTED_SSS,jobID,L"",L"");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
err.SysMsgWrite(ErrE,hr,DCT_MSG_SUBMIT_JOB_FAILED_D,hr);
|
||
|
}
|
||
|
|
||
|
if ( gbDeleteOnCompletion )
|
||
|
{
|
||
|
if ( ! gLocallyInstalled )
|
||
|
{
|
||
|
gSuicide = TRUE;
|
||
|
|
||
|
}
|
||
|
if ( SUCCEEDED(hr) )
|
||
|
{
|
||
|
// Start up a thread to monitor this job and initiate a shutdown when it is completed
|
||
|
DWORD threadID = 0;
|
||
|
HANDLE gThread = CreateThread(NULL,0,&MonitorJob,(void*)jobID,0,&threadID);
|
||
|
|
||
|
CloseHandle(gThread);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
UStrCpy(jobGUID,jobID);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
err.SysMsgWrite(ErrE,HRESULT_CODE(hr),DCT_MSG_VARSET_LOAD_FAILED_SD,filenameW, hr);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
err.SysMsgWrite(ErrE,HRESULT_CODE(hr),DCT_MSG_JOBFILE_OPEN_FAILED_SD,filenameW,hr);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
// int x = pLocalAgent->Release();
|
||
|
pLocalAgent->Release();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
err.SysMsgWrite(ErrE,hr,DCT_MSG_UMARSHAL_AGENT_FAILED_D,hr);
|
||
|
}
|
||
|
CoUninitialize();
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD __stdcall
|
||
|
EaxsCancelJob(
|
||
|
/* [in] */ handle_t hBinding,
|
||
|
/* [string][in] */ const WCHAR __RPC_FAR *jobGUID
|
||
|
)
|
||
|
{
|
||
|
DWORD rc = 0;
|
||
|
HRESULT hr;
|
||
|
IDCTAgent * pLocalAgent = NULL;
|
||
|
|
||
|
// make sure the client is an admin on the local machine
|
||
|
rc = AuthenticateClient(hBinding);
|
||
|
if ( rc )
|
||
|
{
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
hr = CoInitialize(NULL);
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
err.SysMsgWrite(ErrE,hr,DCT_MSG_COINITIALIZE_FAILED_D,hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
hr = CoUnmarshalInterface( pStream, IID_IDCTAgent,(void**)&pLocalAgent);
|
||
|
// interface pointer requested in riid);
|
||
|
|
||
|
if ( SUCCEEDED(hr) )
|
||
|
{
|
||
|
// Reset the stream to the beginning
|
||
|
LARGE_INTEGER offset = { 0,0 };
|
||
|
ULARGE_INTEGER result = { 0,0};
|
||
|
|
||
|
hr = pStream->Seek(offset,STREAM_SEEK_SET,&result);
|
||
|
|
||
|
BSTR jobID;
|
||
|
|
||
|
jobID = SysAllocString(jobGUID);
|
||
|
|
||
|
hr = pLocalAgent->CancelJob(jobID);
|
||
|
if ( SUCCEEDED(hr))
|
||
|
{
|
||
|
err.MsgWrite(0,DCT_MSG_JOB_CANCELLED_S,jobID);
|
||
|
}
|
||
|
pLocalAgent->Release();
|
||
|
rc = hr;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
err.SysMsgWrite(ErrE,hr,DCT_MSG_UMARSHAL_AGENT_FAILED_D,hr);
|
||
|
}
|
||
|
CoUninitialize();
|
||
|
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD __stdcall
|
||
|
EaxsQueryInterface(
|
||
|
/* [in] */ handle_t hBinding,
|
||
|
/* [out] */ LPUNKNOWN __RPC_FAR *lpAgentUnknown
|
||
|
)
|
||
|
{
|
||
|
DWORD rc = 0;
|
||
|
HRESULT hr;
|
||
|
IDCTAgent * pLocalAgent = NULL;
|
||
|
|
||
|
(*lpAgentUnknown) = NULL;
|
||
|
// make sure the client is an admin on the local machine
|
||
|
rc = AuthenticateClient(hBinding);
|
||
|
if ( rc )
|
||
|
{
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
hr = CoInitialize(NULL);
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
err.SysMsgWrite(ErrE,hr,DCT_MSG_COINITIALIZE_FAILED_D,hr);
|
||
|
return hr;
|
||
|
}
|
||
|
//E_NOINTERFACE
|
||
|
if ( ! gbIsNt351 )
|
||
|
{
|
||
|
hr = CoUnmarshalInterface( pStream, IID_IUnknown,(void**)&pLocalAgent);
|
||
|
// interface pointer requested in riid);
|
||
|
|
||
|
if ( SUCCEEDED(hr) )
|
||
|
{
|
||
|
// Reset the stream to the beginning
|
||
|
LARGE_INTEGER offset = { 0,0 };
|
||
|
ULARGE_INTEGER result = { 0,0 };
|
||
|
|
||
|
hr = pStream->Seek(offset,STREAM_SEEK_SET,&result);
|
||
|
|
||
|
(*lpAgentUnknown) = pLocalAgent;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
err.SysMsgWrite(ErrE,hr,DCT_MSG_UMARSHAL_AGENT_FAILED_D,hr);
|
||
|
(*lpAgentUnknown) = NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// NT 3.51 doesn't support DCOM, so there's no point in even trying this
|
||
|
(*lpAgentUnknown) = NULL;
|
||
|
hr = E_NOTIMPL;
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
#define DCTAgent_Remove 1
|
||
|
|
||
|
DWORD __stdcall
|
||
|
ShutdownService(
|
||
|
/* [in] */ DWORD bFlags
|
||
|
)
|
||
|
{
|
||
|
DWORD rc = 0;
|
||
|
HRESULT hr;
|
||
|
// LPUNKNOWN pLocalAgent = NULL;
|
||
|
|
||
|
hr = CoInitialize(NULL);
|
||
|
|
||
|
if ( bFlags )
|
||
|
{
|
||
|
if ( gDebug )
|
||
|
//* err.DbgMsgWrite(0,L"Set suicide flag.");
|
||
|
err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_SETFLAG));
|
||
|
gSuicide = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( gDebug )
|
||
|
//* err.DbgMsgWrite(0,L"Did not set suicide flag");
|
||
|
err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_NOSETFLAG));
|
||
|
}
|
||
|
|
||
|
if ( gSuicide && ! gLocallyInstalled )
|
||
|
{
|
||
|
if ( gDebug )
|
||
|
//* err.DbgMsgWrite(ErrW,L"Removing agent");
|
||
|
err.DbgMsgWrite(ErrW,GET_STRING(IDS_EVENTVW_MSG_REMOVEAGENT));
|
||
|
// Uninstall the service
|
||
|
if ( gDebug )
|
||
|
//* err.DbgMsgWrite(0,L"Unregistering files");
|
||
|
err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_UNREGFILES));
|
||
|
UnregisterFiles();
|
||
|
// delete all files
|
||
|
if ( gDebug )
|
||
|
//* err.DbgMsgWrite(0,L"Deleting files");
|
||
|
err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_FILEDEL));
|
||
|
RemoveFiles();
|
||
|
if ( gDebug )
|
||
|
//* err.DbgMsgWrite(0,L"Removing service");
|
||
|
err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_REMOVESVC));
|
||
|
RemoveService();
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( gDebug )
|
||
|
//* err.DbgMsgWrite(ErrW,L"Not Removing agent");
|
||
|
err.DbgMsgWrite(ErrW,GET_STRING(IDS_EVENTVW_MSG_NOREMOVEAGENT));
|
||
|
}
|
||
|
|
||
|
if ( ! gbIsNt351 )
|
||
|
{
|
||
|
RpcMgmtStopServerListening( NULL );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gbFinished = TRUE;
|
||
|
}
|
||
|
RpcServerUnregisterIf( NULL, NULL, FALSE );
|
||
|
if ( gDebug )
|
||
|
//* err.DbgMsgWrite(0,L"Stopped listening(%ld)",bFlags);
|
||
|
err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_STOPLISTEN),bFlags);
|
||
|
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
DWORD __stdcall
|
||
|
EaxsShutdown(
|
||
|
/* [in] */ handle_t hBinding,
|
||
|
/* [in] */ DWORD bFlags
|
||
|
)
|
||
|
{
|
||
|
DWORD rc = 0;
|
||
|
|
||
|
// make sure the client is an admin on the local machine
|
||
|
rc = AuthenticateClient(hBinding);
|
||
|
if ( rc )
|
||
|
{
|
||
|
return rc;
|
||
|
}
|
||
|
rc = ShutdownService(bFlags);
|
||
|
|
||
|
return rc;
|
||
|
}
|