windows-nt/Source/XPSP1/NT/admin/wmiprov/trustmon/trustmon.cpp
2020-09-26 16:20:57 +08:00

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;
}