572 lines
16 KiB
C++
572 lines
16 KiB
C++
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Windows 2000 Active Directory Service domain trust verification WMI provider
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1992 - 1999
|
||
|
//
|
||
|
// File: trustmon.cpp
|
||
|
//
|
||
|
// Contents: Implementation of worker thread class and DLL Exports.
|
||
|
//
|
||
|
// Classes: CAsyncCallWorker
|
||
|
//
|
||
|
// History: 22-Mar-00 EricB created
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "resource.h"
|
||
|
#include <initguid.h>
|
||
|
|
||
|
CComModule _Module;
|
||
|
|
||
|
DEFINE_GUID(CLSID_TrustMonProvider,0x8065652F,0x4C29,0x4908,0xAA,0xE5,0x20,0x1C,0x89,0x19,0x04,0xC5);
|
||
|
|
||
|
BEGIN_OBJECT_MAP(ObjectMap)
|
||
|
OBJECT_ENTRY(CLSID_TrustMonProvider, CTrustPrv)
|
||
|
END_OBJECT_MAP()
|
||
|
|
||
|
WCHAR g_wzMofPath[] = L"\\system32\\wbem\\ADStatus\\TrustMon.mof";
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Class: CAsyncCallWorker
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CAsyncCallWorker::CAsyncCallWorker(CTrustPrv * pTrustPrv,
|
||
|
long lFlags,
|
||
|
IWbemClassObject * pClassDef,
|
||
|
IWbemObjectSink * pResponseHandler,
|
||
|
LPWSTR pwzInstanceName) :
|
||
|
m_lFlags(lFlags),
|
||
|
m_pwzInstanceName(pwzInstanceName)
|
||
|
{
|
||
|
TRACE(L"CAsyncCallWorker::CAsyncCallWorker(0x%08x)\n", this);
|
||
|
m_sipTrustPrv.p = pTrustPrv; pTrustPrv->AddRef(); // ATL CComPtr is broken!
|
||
|
m_sipClassDef = pClassDef;
|
||
|
m_sipResponseHandler = pResponseHandler;
|
||
|
}
|
||
|
|
||
|
CAsyncCallWorker::~CAsyncCallWorker()
|
||
|
{
|
||
|
TRACE(L"CAsyncCallWorker::~CAsyncCallWorker\n\n");
|
||
|
if (m_pwzInstanceName)
|
||
|
{
|
||
|
delete m_pwzInstanceName;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CAsyncCallWorker::CreateInstEnum
|
||
|
//
|
||
|
// Synopsis: Provides the worker thread function for
|
||
|
// IWbemServices::CreateInstanceEnumAsync
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void __cdecl
|
||
|
CAsyncCallWorker::CreateInstEnum(PVOID pParam)
|
||
|
{
|
||
|
TRACE(L"CAsyncCallWorker::CreateInstEnum\n");
|
||
|
HRESULT hr = WBEM_S_NO_ERROR;
|
||
|
DWORD dwWaitResult;
|
||
|
CAsyncCallWorker * pWorker = (CAsyncCallWorker *)pParam;
|
||
|
CDomainInfo * pDomain = &(pWorker->m_sipTrustPrv->m_DomainInfo);
|
||
|
|
||
|
CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||
|
|
||
|
do
|
||
|
{
|
||
|
BREAK_ON_NULL(pWorker);
|
||
|
|
||
|
//
|
||
|
// Try to get the mutex first without a wait. It is in the signalled state if
|
||
|
// not owned.
|
||
|
//
|
||
|
dwWaitResult = WaitForSingleObject(pWorker->m_sipTrustPrv->m_hMutex, 0);
|
||
|
|
||
|
if (WAIT_TIMEOUT == dwWaitResult)
|
||
|
{
|
||
|
// Mutex is owned by another thread. Rewait.
|
||
|
|
||
|
dwWaitResult = WaitForSingleObject(pWorker->m_sipTrustPrv->m_hMutex,
|
||
|
6000000); // timeout set to 10 minutes
|
||
|
|
||
|
switch(dwWaitResult)
|
||
|
{
|
||
|
case WAIT_TIMEOUT:
|
||
|
// mutex continues to be non-signalled (owned by another thread).
|
||
|
hr = WBEM_E_SERVER_TOO_BUSY; // BUGBUG: returning an error.
|
||
|
// BUGBUG: should the timeout be parameterized?
|
||
|
break;
|
||
|
|
||
|
case WAIT_OBJECT_0:
|
||
|
// This thread now owns the mutex.
|
||
|
break;
|
||
|
|
||
|
case WAIT_ABANDONED: // this means the owning thread terminated without releasing the mutex.
|
||
|
TRACE(L"Another thread didn't release the mutex!\n");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BREAK_ON_FAIL;
|
||
|
|
||
|
CoImpersonateClient();
|
||
|
|
||
|
//
|
||
|
// Re-read all the trust information if stale.
|
||
|
// The trust list is not re-enumerated on every call because trusts are
|
||
|
// rarely modified.
|
||
|
//
|
||
|
if (pDomain->IsTrustListStale(pWorker->m_sipTrustPrv->m_liTrustEnumMaxAge))
|
||
|
{
|
||
|
hr = pDomain->EnumerateTrusts();
|
||
|
|
||
|
BREAK_ON_FAIL;
|
||
|
}
|
||
|
|
||
|
size_t cTrusts = pDomain->Size();
|
||
|
|
||
|
for (size_t i = 0; i < cTrusts; i++)
|
||
|
{
|
||
|
if ((long)WBEM_FLAG_SEND_STATUS & pWorker->m_lFlags)
|
||
|
{
|
||
|
hr = pWorker->m_sipResponseHandler->SetStatus(WBEM_STATUS_PROGRESS,
|
||
|
MAKELONG(i, cTrusts),
|
||
|
NULL, NULL);
|
||
|
BREAK_ON_FAIL;
|
||
|
}
|
||
|
|
||
|
CTrustInfo * pTrust;
|
||
|
|
||
|
//
|
||
|
// Get trust Info
|
||
|
//
|
||
|
pTrust = pDomain->GetTrustByIndex(i);
|
||
|
|
||
|
BREAK_ON_NULL_(pTrust, hr, WBEM_E_INVALID_OBJECT_PATH);
|
||
|
|
||
|
//
|
||
|
// Verify the trust if stale.
|
||
|
//
|
||
|
if (pTrust->IsVerificationStale(pWorker->m_sipTrustPrv->m_liVerifyMaxAge))
|
||
|
{
|
||
|
pTrust->Verify(pWorker->m_sipTrustPrv->GetTrustCheckLevel());
|
||
|
}
|
||
|
|
||
|
CoRevertToSelf();
|
||
|
|
||
|
//
|
||
|
// Create a new instance of the object if the trust is outbound or if
|
||
|
// return-all is true.
|
||
|
//
|
||
|
if (pTrust->IsTrustOutbound() || pWorker->m_sipTrustPrv->GetReturnAll())
|
||
|
{
|
||
|
hr = CreateAndSendTrustInst(*pTrust, pWorker->m_sipClassDef,
|
||
|
pWorker->m_sipResponseHandler);
|
||
|
}
|
||
|
|
||
|
BREAK_ON_FAIL;
|
||
|
|
||
|
CoImpersonateClient();
|
||
|
}
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
CoRevertToSelf();
|
||
|
|
||
|
//
|
||
|
// Set status
|
||
|
//
|
||
|
pWorker->m_sipResponseHandler->SetStatus(WBEM_STATUS_COMPLETE, hr, NULL, NULL);
|
||
|
|
||
|
ReleaseMutex(pWorker->m_sipTrustPrv->m_hMutex);
|
||
|
|
||
|
delete pWorker;
|
||
|
|
||
|
CoUninitialize();
|
||
|
|
||
|
_endthread();
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CAsyncCallWorker::GetObj
|
||
|
//
|
||
|
// Synopsis: Provides the worker thread function for
|
||
|
// IWbemServices::GetObjectAsync
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void __cdecl
|
||
|
CAsyncCallWorker::GetObj(PVOID pParam)
|
||
|
{
|
||
|
TRACE(L"CAsyncCallWorker::GetObj\n");
|
||
|
HRESULT hr = WBEM_S_NO_ERROR;
|
||
|
CAsyncCallWorker * pWorker = (CAsyncCallWorker *)pParam;
|
||
|
|
||
|
CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||
|
|
||
|
CoImpersonateClient();
|
||
|
|
||
|
do
|
||
|
{
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
CoRevertToSelf();
|
||
|
|
||
|
//
|
||
|
// Set status
|
||
|
//
|
||
|
pWorker->m_sipResponseHandler->SetStatus(WBEM_STATUS_COMPLETE, hr, NULL, NULL);
|
||
|
|
||
|
delete pWorker;
|
||
|
|
||
|
CoUninitialize();
|
||
|
|
||
|
_endthread();
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: CreateAndSendTrustInst
|
||
|
//
|
||
|
// Purpose: Creates a new instance and sets the inital values of the
|
||
|
// properties.
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
CreateAndSendTrustInst(CTrustInfo & Trust, IWbemClassObject * pClassDef,
|
||
|
IWbemObjectSink * pResponseHandler)
|
||
|
{
|
||
|
TRACE(L"CreateAndSendTrustInst\n");
|
||
|
HRESULT hr = WBEM_S_NO_ERROR;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
CComPtr<IWbemClassObject> ipNewInst;
|
||
|
CComVariant var;
|
||
|
|
||
|
//
|
||
|
// Create a new instance of the WMI class object
|
||
|
//
|
||
|
hr = pClassDef->SpawnInstance(0, &ipNewInst);
|
||
|
BREAK_ON_FAIL;
|
||
|
|
||
|
// Set the key property value (TrustedDomain)
|
||
|
var = Trust.GetTrustedDomain();
|
||
|
hr = ipNewInst->Put(CSTR_PROP_TRUSTED_DOMAIN, 0, &var, 0);
|
||
|
TRACE(L"\tCreating instance %s\n", var.bstrVal);
|
||
|
BREAK_ON_FAIL;
|
||
|
//Flat Name
|
||
|
var = Trust.GetFlatName();
|
||
|
hr = ipNewInst->Put(CSTR_PROP_FLAT_NAME, 0, &var, 0);
|
||
|
BREAK_ON_FAIL;
|
||
|
//Sid
|
||
|
var = Trust.GetSid();
|
||
|
hr = ipNewInst->Put(CSTR_PROP_SID, 0, &var, 0);
|
||
|
BREAK_ON_FAIL;
|
||
|
//Trust Direction
|
||
|
var = (long)Trust.GetTrustDirection();
|
||
|
hr = ipNewInst->Put(CSTR_PROP_TRUST_DIRECTION, 0, &var, 0);
|
||
|
BREAK_ON_FAIL;
|
||
|
//Trust Type
|
||
|
var = (long)Trust.GetTrustType();
|
||
|
hr = ipNewInst->Put(CSTR_PROP_TRUST_TYPE, 0, &var, 0);
|
||
|
BREAK_ON_FAIL;
|
||
|
//Trust Attributes
|
||
|
var = (long)Trust.GetTrustAttributes();
|
||
|
hr = ipNewInst->Put(CSTR_PROP_TRUST_ATTRIBUTES, 0, &var, 0);
|
||
|
BREAK_ON_FAIL;
|
||
|
// Set the TrustStatus value.
|
||
|
var = (long)Trust.GetTrustStatus();
|
||
|
hr = ipNewInst->Put(CSTR_PROP_TRUST_STATUS, 0, &var, 0);
|
||
|
BREAK_ON_FAIL;
|
||
|
var = Trust.GetTrustStatusString();
|
||
|
hr = ipNewInst->Put(CSTR_PROP_TRUST_STATUS_STRING, 0, &var, 0);
|
||
|
BREAK_ON_FAIL;
|
||
|
// Set the Trust Is OK value.
|
||
|
var = Trust.IsTrustOK();
|
||
|
hr = ipNewInst->Put(CSTR_PROP_TRUST_IS_OK, 0, &var, 0);
|
||
|
BREAK_ON_FAIL;
|
||
|
//Trusted DC Name
|
||
|
var = Trust.GetTrustedDCName();
|
||
|
hr = ipNewInst->Put(CSTR_PROP_TRUSTED_DC_NAME, 0, &var, 0);
|
||
|
BREAK_ON_FAIL;
|
||
|
|
||
|
//
|
||
|
// Send the object to the caller
|
||
|
//
|
||
|
// [In] param, no need to addref.
|
||
|
IWbemClassObject * pNewInstance = ipNewInst;
|
||
|
hr = pResponseHandler->Indicate(1, &pNewInstance);
|
||
|
|
||
|
BREAK_ON_FAIL;
|
||
|
|
||
|
} while(FALSE);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DllMain
|
||
|
//
|
||
|
// Purpose: DLL Entry Point
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
extern "C" BOOL WINAPI
|
||
|
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||
|
{
|
||
|
if (dwReason == DLL_PROCESS_ATTACH)
|
||
|
{
|
||
|
_Module.Init(ObjectMap, hInstance);
|
||
|
DisableThreadLibraryCalls(hInstance);
|
||
|
}
|
||
|
else if (dwReason == DLL_PROCESS_DETACH)
|
||
|
_Module.Term();
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DllCanUnloadNow
|
||
|
//
|
||
|
// Purpose: Used to determine whether the DLL can be unloaded by OLE
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
STDAPI DllCanUnloadNow(void)
|
||
|
{
|
||
|
return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DllGetClassObject
|
||
|
//
|
||
|
// Purpose: Returns a class factory to create an object of the requested type
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
|
||
|
{
|
||
|
return _Module.GetClassObject(rclsid, riid, ppv);
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DllRegisterServer
|
||
|
//
|
||
|
// Purpose: Adds Class entries to the system registry
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
STDAPI DllRegisterServer(void)
|
||
|
{
|
||
|
// Add TrustMon to the registry as an event source.
|
||
|
//
|
||
|
HKEY hk;
|
||
|
DWORD dwData;
|
||
|
WCHAR wzFilePath[2*MAX_PATH];
|
||
|
|
||
|
GetModuleFileName(_Module.GetModuleInstance(), wzFilePath, 2*MAX_PATH);
|
||
|
|
||
|
if (RegCreateKey(HKEY_LOCAL_MACHINE,
|
||
|
L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" TM_PROV_NAME,
|
||
|
&hk))
|
||
|
{
|
||
|
TRACE(L"Could not create the registry key.");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Set the name of the message file.
|
||
|
//
|
||
|
TRACE(L"Adding path %s to the registry\n", wzFilePath);
|
||
|
|
||
|
// Add the name to the EventMessageFile subkey.
|
||
|
|
||
|
if (RegSetValueEx(hk,
|
||
|
L"EventMessageFile",
|
||
|
0,
|
||
|
REG_EXPAND_SZ,
|
||
|
(LPBYTE)wzFilePath,
|
||
|
(ULONG)(wcslen(wzFilePath) + 1) * sizeof(WCHAR)))
|
||
|
{
|
||
|
TRACE(L"Could not set the event message file.");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Set the supported event types in the TypesSupported subkey.
|
||
|
|
||
|
dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
|
||
|
EVENTLOG_INFORMATION_TYPE;
|
||
|
|
||
|
if (RegSetValueEx(hk,
|
||
|
L"TypesSupported",
|
||
|
0,
|
||
|
REG_DWORD,
|
||
|
(LPBYTE)&dwData,
|
||
|
sizeof(DWORD)))
|
||
|
{
|
||
|
TRACE(L"Could not set the supported types.");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RegCloseKey(hk);
|
||
|
}
|
||
|
|
||
|
// Add a RunOnce value to do the MOF compile.
|
||
|
//
|
||
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||
|
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
|
||
|
0,
|
||
|
KEY_WRITE,
|
||
|
&hk))
|
||
|
{
|
||
|
TRACE(L"Could not open the registry key.");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CString csCmd = L"rundll32.exe ";
|
||
|
csCmd += wzFilePath;
|
||
|
csCmd += L",DoMofComp";
|
||
|
|
||
|
if (RegSetValueEx(hk,
|
||
|
L"TrustMon",
|
||
|
0,
|
||
|
REG_SZ,
|
||
|
(LPBYTE)csCmd.GetBuffer(0),
|
||
|
csCmd.GetLength() * sizeof(WCHAR)))
|
||
|
{
|
||
|
TRACE(L"Could not set the runonce value.");
|
||
|
}
|
||
|
|
||
|
RegCloseKey(hk);
|
||
|
}
|
||
|
|
||
|
return _Module.RegisterServer();
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DllUnregisterServer
|
||
|
//
|
||
|
// Purpose: Removes Class entries from the system registry
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
STDAPI DllUnregisterServer(void)
|
||
|
{
|
||
|
return _Module.UnregisterServer();
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DoMofComp
|
||
|
//
|
||
|
// Purpose: Adds the provider classes to the WMI repository. Note that the
|
||
|
// function signature is that required by rundll32.exe.
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
VOID WINAPI DoMofComp(HWND hWndParent,
|
||
|
HINSTANCE hModule,
|
||
|
PCTSTR ptzCommandLine,
|
||
|
INT nShowCmd)
|
||
|
{
|
||
|
TRACE(L"DoMofComp\n");
|
||
|
UNREFERENCED_PARAMETER(hWndParent);
|
||
|
UNREFERENCED_PARAMETER(hModule);
|
||
|
UNREFERENCED_PARAMETER(ptzCommandLine);
|
||
|
UNREFERENCED_PARAMETER(nShowCmd);
|
||
|
HRESULT hr;
|
||
|
CComPtr<IMofCompiler> pmc;
|
||
|
|
||
|
CoInitialize(NULL);
|
||
|
|
||
|
hr = CoCreateInstance(CLSID_MofCompiler, NULL, CLSCTX_INPROC_SERVER,
|
||
|
IID_IMofCompiler, (PVOID *)&pmc);
|
||
|
|
||
|
CHECK_HRESULT(hr, return);
|
||
|
|
||
|
WCHAR wzFilePath[2*MAX_PATH];
|
||
|
UINT nLen = GetSystemWindowsDirectory(wzFilePath, 2*MAX_PATH);
|
||
|
if (nLen == 0)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
CString csMofPath = wzFilePath;
|
||
|
|
||
|
csMofPath += g_wzMofPath;
|
||
|
|
||
|
WBEM_COMPILE_STATUS_INFO Info;
|
||
|
|
||
|
TRACE(L"Compiling MOF file %s\n", csMofPath.GetBuffer(0));
|
||
|
|
||
|
hr = pmc->CompileFile(csMofPath.GetBuffer(0), NULL, NULL, NULL, NULL,
|
||
|
WBEM_FLAG_AUTORECOVER, 0, 0, &Info);
|
||
|
|
||
|
HANDLE hEvent = RegisterEventSource(NULL, TM_PROV_NAME);
|
||
|
|
||
|
if (!hEvent)
|
||
|
{
|
||
|
TRACE(L"RegisterEventSource failed with error %d\n", GetLastError());
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (WBEM_S_NO_ERROR != hr)
|
||
|
{
|
||
|
TRACE(L"MofCompile failed with error 0x%08x (WMI error 0x%08x), line: %d, phase: %d\n",
|
||
|
hr, Info.hRes, Info.FirstLine, Info.lPhaseError);
|
||
|
//
|
||
|
// Send failure to EventLog.
|
||
|
//
|
||
|
CString csHr, csLine;
|
||
|
HMODULE hm = LoadLibrary(L"mofd.dll");
|
||
|
|
||
|
if (hm)
|
||
|
{
|
||
|
WCHAR wzBuf[MAX_PATH];
|
||
|
LoadString(hm, Info.hRes, wzBuf, MAX_PATH);
|
||
|
csHr = wzBuf;
|
||
|
FreeLibrary(hm);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
csHr.Format(L"%d", Info.hRes);
|
||
|
}
|
||
|
|
||
|
csLine.Format(L"%d", Info.FirstLine);
|
||
|
const PWSTR rgArgs[3] = {csHr.GetBuffer(0), csLine.GetBuffer(0), csMofPath.GetBuffer(0)};
|
||
|
|
||
|
ReportEvent(hEvent,
|
||
|
EVENTLOG_ERROR_TYPE,
|
||
|
0, // wCategory
|
||
|
TRUSTMON_MOFCOMP_FAILED, // dwEventID
|
||
|
NULL, // lpUserSID
|
||
|
3, // wNumStrings
|
||
|
0, // dwDataSize
|
||
|
(PCWSTR *)rgArgs, // lpStrings
|
||
|
NULL); // lpRawData
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Send success notice to EventLog.
|
||
|
//
|
||
|
ReportEvent(hEvent,
|
||
|
EVENTLOG_INFORMATION_TYPE,
|
||
|
0, // wCategory
|
||
|
TRUSTMON_MOFCOMP_SUCCESS, // dwEventID
|
||
|
NULL, // lpUserSID
|
||
|
0, // wNumStrings
|
||
|
0, // dwDataSize
|
||
|
NULL, // lpStrings
|
||
|
NULL); // lpRawData
|
||
|
}
|
||
|
|
||
|
DeregisterEventSource(hEvent);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|