1035 lines
30 KiB
C++
1035 lines
30 KiB
C++
#undef _WIN32_WINNT
|
|
#define _WIN32_WINNT 0x0500
|
|
|
|
#include <wbemcli.h>
|
|
#include <wbemprov.h>
|
|
#include <atlbase.h>
|
|
#include <stdio.h> // fprintf
|
|
#include <stdlib.h>
|
|
#include <locale.h>
|
|
|
|
#include <genlex.h>
|
|
#include <qllex.h>
|
|
#include <ql.h>
|
|
#include <ntdsapi.h>
|
|
|
|
#include "objpath.h"
|
|
#include "iads.h"
|
|
#include "adshlp.h"
|
|
|
|
#include "Utility.h"
|
|
|
|
#include <SDDL.H>
|
|
|
|
|
|
BSTR
|
|
// **** misc names
|
|
|
|
g_bstrEmptyString = NULL,
|
|
g_bstrEmptyDate = NULL,
|
|
|
|
// **** AD schema names
|
|
|
|
g_bstrADAuthor = NULL,
|
|
g_bstrADChangeDate = NULL,
|
|
g_bstrADClassDefinition = NULL,
|
|
g_bstrADCreationDate = NULL,
|
|
g_bstrADDescription = NULL,
|
|
g_bstrADIntDefault = NULL,
|
|
g_bstrADInt8Default = NULL,
|
|
g_bstrADID = NULL,
|
|
g_bstrADIntMax = NULL,
|
|
g_bstrADInt8Max = NULL,
|
|
g_bstrADIntMin = NULL,
|
|
g_bstrADInt8Min = NULL,
|
|
g_bstrADIntValidValues = NULL,
|
|
g_bstrADName = NULL,
|
|
g_bstrADNormalizedClass = NULL,
|
|
g_bstrADObjectClass = NULL,
|
|
g_bstrADParam2 = NULL,
|
|
g_bstrADPolicyType = NULL,
|
|
g_bstrADPropertyName = NULL,
|
|
g_bstrADQuery = NULL,
|
|
g_bstrADQueryLanguage = NULL,
|
|
g_bstrADSourceOrganization = NULL,
|
|
g_bstrADStringDefault = NULL,
|
|
g_bstrADStringValidValues = NULL,
|
|
g_bstrADTargetClass = NULL,
|
|
g_bstrADTargetNameSpace = NULL,
|
|
g_bstrADTargetObject = NULL,
|
|
g_bstrADTargetPath = NULL,
|
|
g_bstrADTargetType = NULL,
|
|
|
|
// **** AD class names
|
|
|
|
g_bstrADClassMergeablePolicy = NULL,
|
|
g_bstrADClassRangeParam = NULL,
|
|
g_bstrADClassRangeSint32 = NULL,
|
|
g_bstrADClassRangeUint32 = NULL,
|
|
g_bstrADClassRangeReal = NULL,
|
|
g_bstrADClassParamUnknown = NULL,
|
|
g_bstrADClassSetSint32 = NULL,
|
|
g_bstrADClassSetUint32 = NULL,
|
|
g_bstrADClassSetString = NULL,
|
|
g_bstrADClassSimplePolicy = NULL,
|
|
g_bstrADClassRule = NULL,
|
|
g_bstrADClassSom = NULL,
|
|
g_bstrADClassPolicyType = NULL,
|
|
g_bstrADClassWMIGPO = NULL,
|
|
|
|
// **** CIM schema names
|
|
|
|
g_bstrAuthor = NULL,
|
|
g_bstrChangeDate = NULL,
|
|
g_bstrClassDefinition = NULL,
|
|
g_bstrCreationDate = NULL,
|
|
g_bstrDefault = NULL,
|
|
g_bstrDescription = NULL,
|
|
g_bstrDsPath = NULL,
|
|
g_bstrDomain = NULL,
|
|
g_bstrID = NULL,
|
|
g_bstrMax = NULL,
|
|
g_bstrMin = NULL,
|
|
g_bstrName = NULL,
|
|
g_bstrPolicyType = NULL,
|
|
g_bstrPropertyName = NULL,
|
|
g_bstrQuery = NULL,
|
|
g_bstrQueryLanguage = NULL,
|
|
g_bstrRangeSettings = NULL,
|
|
g_bstrRules = NULL,
|
|
g_bstrSourceOrganization = NULL,
|
|
g_bstrTargetClass = NULL,
|
|
g_bstrTargetNameSpace = NULL,
|
|
g_bstrTargetObject = NULL,
|
|
g_bstrTargetPath = NULL,
|
|
g_bstrTargetType = NULL,
|
|
g_bstrValidValues = NULL,
|
|
|
|
// **** CIM class names
|
|
|
|
g_bstrClassMergeablePolicy = NULL,
|
|
g_bstrClassRangeParam = NULL,
|
|
g_bstrClassRangeSint32 = NULL,
|
|
g_bstrClassRangeUint32 = NULL,
|
|
g_bstrClassRangeReal = NULL,
|
|
g_bstrClassSetSint32 = NULL,
|
|
g_bstrClassSetUint32 = NULL,
|
|
g_bstrClassSetString = NULL,
|
|
g_bstrClassSimplePolicy = NULL,
|
|
g_bstrClassRule = NULL,
|
|
g_bstrClassSom = NULL,
|
|
g_bstrClassPolicyType = NULL,
|
|
g_bstrClassWMIGPO = NULL;
|
|
|
|
void InitGlobalNames(void)
|
|
{
|
|
// **** misc names
|
|
|
|
g_bstrEmptyString = SysAllocString(L" ");
|
|
g_bstrEmptyDate = SysAllocString(L"00000000000000.000000-000");
|
|
|
|
// **** AD schema names
|
|
|
|
g_bstrADAuthor = SysAllocString(L"msWMI-Author");
|
|
g_bstrADChangeDate = SysAllocString(L"msWMI-ChangeDate");
|
|
g_bstrADClassDefinition = SysAllocString(L"msWMI-ClassDefinition"),
|
|
g_bstrADCreationDate = SysAllocString(L"msWMI-CreationDate");
|
|
g_bstrADDescription = SysAllocString(L"msWMI-Parm1");
|
|
g_bstrADIntDefault = SysAllocString(L"msWMI-IntDefault");
|
|
g_bstrADInt8Default = SysAllocString(L"msWMI-Int8Default");
|
|
g_bstrADID = SysAllocString(L"msWMI-ID");
|
|
g_bstrADIntMax = SysAllocString(L"msWMI-IntMax");
|
|
g_bstrADInt8Max = SysAllocString(L"msWMI-Int8Max");
|
|
g_bstrADIntMin = SysAllocString(L"msWMI-IntMin");
|
|
g_bstrADInt8Min = SysAllocString(L"msWMI-Int8Min");
|
|
g_bstrADIntValidValues = SysAllocString(L"msWMI-IntValidValues");
|
|
g_bstrADName = SysAllocString(L"msWMI-Name");
|
|
g_bstrADNormalizedClass = SysAllocString(L"msWMI-NormalizedClass");
|
|
g_bstrADObjectClass = SysAllocString(L"objectClass"),
|
|
g_bstrADParam2 = SysAllocString(L"msWMI-Parm2"),
|
|
g_bstrADPolicyType = SysAllocString(L"msWMI-PolicyType");
|
|
g_bstrADPropertyName = SysAllocString(L"msWMI-PropertyName");
|
|
g_bstrADQuery = SysAllocString(L"msWMI-Query"),
|
|
g_bstrADQueryLanguage = SysAllocString(L"msWMI-QueryLanguage"),
|
|
g_bstrADStringDefault = SysAllocString(L"msWMI-StringDefault");
|
|
g_bstrADStringValidValues = SysAllocString(L"msWMI-StringValidValues");
|
|
g_bstrADSourceOrganization = SysAllocString(L"msWMI-SourceOrganization");
|
|
g_bstrADTargetClass = SysAllocString(L"msWMI-TargetClass");
|
|
g_bstrADTargetNameSpace = SysAllocString(L"msWMI-TargetNameSpace");
|
|
g_bstrADTargetObject = SysAllocString(L"msWMI-TargetObject"),
|
|
g_bstrADTargetPath = SysAllocString(L"msWMI-TargetPath"),
|
|
g_bstrADTargetType = SysAllocString(L"msWMI-TargetType"),
|
|
|
|
// **** AD class names
|
|
|
|
g_bstrADClassMergeablePolicy = SysAllocString(L"msWMI-MergeablePolicyTemplate");
|
|
g_bstrADClassRangeParam = SysAllocString(L"msWMI-RangeParam");
|
|
g_bstrADClassRangeSint32 = SysAllocString(L"msWMI-IntRangeParam");
|
|
g_bstrADClassRangeUint32 = SysAllocString(L"msWMI-UintRangeParam");
|
|
g_bstrADClassRangeReal = SysAllocString(L"msWMI-RealRangeParam");
|
|
g_bstrADClassParamUnknown = SysAllocString(L"msWMI-UnknownRangeParam");
|
|
g_bstrADClassSetSint32 = SysAllocString(L"msWMI-IntSetParam");
|
|
g_bstrADClassSetUint32 = SysAllocString(L"msWMI-UintSetParam");
|
|
g_bstrADClassSetString = SysAllocString(L"msWMI-StringSetParam");
|
|
g_bstrADClassSimplePolicy = SysAllocString(L"msWMI-SimplePolicyTemplate");
|
|
g_bstrADClassRule = SysAllocString(L"msWMI-Rule");
|
|
g_bstrADClassSom = SysAllocString(L"msWMI-SOM");
|
|
g_bstrADClassPolicyType = SysAllocString(L"msWMI-PolicyType");
|
|
g_bstrADClassWMIGPO = SysAllocString(L"msWMI-WMIGPO");
|
|
|
|
// **** CIM Attribute Names
|
|
|
|
g_bstrAuthor = SysAllocString(L"Author");
|
|
g_bstrChangeDate = SysAllocString(L"ChangeDate");
|
|
g_bstrClassDefinition = SysAllocString(L"ClassDefinition"),
|
|
g_bstrCreationDate = SysAllocString(L"CreationDate");
|
|
g_bstrDefault = SysAllocString(L"Default");
|
|
g_bstrDescription = SysAllocString(L"Description");
|
|
g_bstrDsPath = SysAllocString(L"DsPath");
|
|
g_bstrDomain = SysAllocString(L"Domain");
|
|
g_bstrID = SysAllocString(L"ID");
|
|
g_bstrMax = SysAllocString(L"Max");
|
|
g_bstrMin = SysAllocString(L"Min");
|
|
g_bstrName = SysAllocString(L"Name");
|
|
g_bstrPolicyType = SysAllocString(L"PolicyType");
|
|
g_bstrPropertyName = SysAllocString(L"PropertyName");
|
|
g_bstrQuery = SysAllocString(L"query");
|
|
g_bstrQueryLanguage = SysAllocString(L"QueryLanguage");
|
|
g_bstrRangeSettings = SysAllocString(L"RangeSettings");
|
|
g_bstrRules = SysAllocString(L"Rules");
|
|
g_bstrSourceOrganization = SysAllocString(L"SourceOrganization");
|
|
g_bstrTargetClass = SysAllocString(L"TargetClass"),
|
|
g_bstrTargetNameSpace = SysAllocString(L"TargetNamespace");
|
|
g_bstrTargetObject = SysAllocString(L"TargetObject"),
|
|
g_bstrTargetPath = SysAllocString(L"TargetPath"),
|
|
g_bstrTargetType = SysAllocString(L"TargetType"),
|
|
g_bstrValidValues = SysAllocString(L"ValidValues");
|
|
|
|
// **** CIM class names
|
|
|
|
g_bstrClassMergeablePolicy = SysAllocString(L"MSFT_MergeablePolicyTemplate");
|
|
g_bstrClassRangeParam = SysAllocString(L"MSFT_RangeParam");
|
|
g_bstrClassRangeSint32 = SysAllocString(L"MSFT_SintRangeParam");
|
|
g_bstrClassRangeUint32 = SysAllocString(L"MSFT_UintRangeParam");
|
|
g_bstrClassRangeReal = SysAllocString(L"MSFT_RealRangeParam");
|
|
g_bstrClassSetSint32 = SysAllocString(L"MSFT_SintSetParam");
|
|
g_bstrClassSetUint32 = SysAllocString(L"MSFT_UintSetParam");
|
|
g_bstrClassSetString = SysAllocString(L"MSFT_StringSetParam");
|
|
g_bstrClassSimplePolicy = SysAllocString(L"MSFT_SimplePolicyTemplate");
|
|
g_bstrClassRule = SysAllocString(L"MSFT_Rule");
|
|
g_bstrClassSom = SysAllocString(L"MSFT_SomFilter");
|
|
g_bstrClassPolicyType = SysAllocString(L"MSFT_PolicyType");
|
|
g_bstrClassWMIGPO = SysAllocString(L"MSFT_WMIGPO");
|
|
}
|
|
|
|
void FreeGlobalNames(void)
|
|
{
|
|
// **** misc names
|
|
|
|
SysFreeString(g_bstrEmptyString);
|
|
SysFreeString(g_bstrEmptyDate);
|
|
|
|
// **** AD schema names
|
|
|
|
SysFreeString(g_bstrADAuthor);
|
|
SysFreeString(g_bstrADChangeDate);
|
|
SysFreeString(g_bstrADClassDefinition);
|
|
SysFreeString(g_bstrADCreationDate);
|
|
SysFreeString(g_bstrADIntDefault);
|
|
SysFreeString(g_bstrADInt8Default);
|
|
SysFreeString(g_bstrADID);
|
|
SysFreeString(g_bstrADIntMax);
|
|
SysFreeString(g_bstrADInt8Max);
|
|
SysFreeString(g_bstrADIntMin);
|
|
SysFreeString(g_bstrADInt8Min);
|
|
SysFreeString(g_bstrADIntValidValues);
|
|
SysFreeString(g_bstrADName);
|
|
SysFreeString(g_bstrADNormalizedClass);
|
|
SysFreeString(g_bstrADObjectClass);
|
|
SysFreeString(g_bstrADParam2),
|
|
SysFreeString(g_bstrADPolicyType);
|
|
SysFreeString(g_bstrADPropertyName);
|
|
SysFreeString(g_bstrADQuery);
|
|
SysFreeString(g_bstrADQueryLanguage);
|
|
SysFreeString(g_bstrADStringDefault);
|
|
SysFreeString(g_bstrADStringValidValues);
|
|
SysFreeString(g_bstrADSourceOrganization);
|
|
SysFreeString(g_bstrADTargetClass);
|
|
SysFreeString(g_bstrADTargetNameSpace);
|
|
SysFreeString(g_bstrADTargetObject);
|
|
SysFreeString(g_bstrADTargetPath);
|
|
SysFreeString(g_bstrADTargetType);
|
|
|
|
// **** AD class names
|
|
|
|
SysFreeString(g_bstrADClassMergeablePolicy);
|
|
SysFreeString(g_bstrADClassRangeParam);
|
|
SysFreeString(g_bstrADClassRangeSint32);
|
|
SysFreeString(g_bstrADClassRangeUint32);
|
|
SysFreeString(g_bstrADClassRangeReal);
|
|
SysFreeString(g_bstrADClassParamUnknown);
|
|
SysFreeString(g_bstrADClassSetSint32);
|
|
SysFreeString(g_bstrADClassSetUint32);
|
|
SysFreeString(g_bstrADClassSetString);
|
|
SysFreeString(g_bstrADClassSimplePolicy);
|
|
SysFreeString(g_bstrADClassRule);
|
|
SysFreeString(g_bstrADClassSom);
|
|
SysFreeString(g_bstrADClassPolicyType);
|
|
SysFreeString(g_bstrADClassWMIGPO);
|
|
|
|
// **** CIM Attribute Names
|
|
|
|
SysFreeString(g_bstrAuthor);
|
|
SysFreeString(g_bstrChangeDate);
|
|
SysFreeString(g_bstrClassDefinition);
|
|
SysFreeString(g_bstrCreationDate);
|
|
SysFreeString(g_bstrDefault);
|
|
SysFreeString(g_bstrDsPath);
|
|
SysFreeString(g_bstrDomain);
|
|
SysFreeString(g_bstrID);
|
|
SysFreeString(g_bstrMax);
|
|
SysFreeString(g_bstrMin);
|
|
SysFreeString(g_bstrName);
|
|
SysFreeString(g_bstrPolicyType);
|
|
SysFreeString(g_bstrPropertyName);
|
|
SysFreeString(g_bstrQuery);
|
|
SysFreeString(g_bstrQueryLanguage);
|
|
SysFreeString(g_bstrRangeSettings);
|
|
SysFreeString(g_bstrRules);
|
|
SysFreeString(g_bstrSourceOrganization);
|
|
SysFreeString(g_bstrTargetClass);
|
|
SysFreeString(g_bstrTargetNameSpace);
|
|
SysFreeString(g_bstrTargetObject);
|
|
SysFreeString(g_bstrTargetPath);
|
|
SysFreeString(g_bstrTargetType);
|
|
SysFreeString(g_bstrValidValues);
|
|
|
|
// **** CIM class names
|
|
|
|
SysFreeString(g_bstrClassMergeablePolicy);
|
|
SysFreeString(g_bstrClassRangeParam);
|
|
SysFreeString(g_bstrClassRangeSint32);
|
|
SysFreeString(g_bstrClassRangeUint32);
|
|
SysFreeString(g_bstrClassRangeReal);
|
|
SysFreeString(g_bstrClassSetSint32);
|
|
SysFreeString(g_bstrClassSetUint32);
|
|
SysFreeString(g_bstrClassSetString);
|
|
SysFreeString(g_bstrClassSimplePolicy);
|
|
SysFreeString(g_bstrClassRule);
|
|
SysFreeString(g_bstrClassSom);
|
|
SysFreeString(g_bstrClassPolicyType);
|
|
SysFreeString(g_bstrClassWMIGPO);
|
|
}
|
|
|
|
// TODO: attempt to create namespace if not available.
|
|
HRESULT GetNamespace(BSTR namespaceName, IWbemServices*& pNamespace, bool bInProc)
|
|
{
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
|
|
IWbemLocator* pLoc = NULL;
|
|
|
|
if (FAILED(hr = CoCreateInstance(bInProc ? CLSID_WbemAdministrativeLocator : CLSID_WbemLocator,
|
|
0, CLSCTX_ALL, IID_IWbemLocator,
|
|
(LPVOID*) &pLoc)))
|
|
ERRORTRACE((LOG_ESS, "Could not create wbem locator (0x%08X)\n", hr));
|
|
else
|
|
{
|
|
DEBUGTRACE((LOG_ESS, "Created Locator\n"));
|
|
if (FAILED(hr = pLoc->ConnectServer(namespaceName, NULL,NULL, 0,0,0,0,&pNamespace)))
|
|
ERRORTRACE((LOG_ESS, "ConnectServer(%S) failed (0x%08X)\n", namespaceName, hr));
|
|
else
|
|
DEBUGTRACE((LOG_ESS, "ConnectServer(%S) succeeded (0x%08X)\n", namespaceName, hr));
|
|
|
|
pLoc->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// make sure that the ID property of pObj has a value
|
|
// assumes property is a BSTR!
|
|
// will generate GUID if not
|
|
// if pName == NULL, assumes property name is "ID"
|
|
// returns WBEM_S_NO_ERROR if ID generated
|
|
// WBEM_S_FALSE if no ID generated (already has a value)
|
|
// WBEM_E_NOT_FOUND if ID property is not
|
|
// some error if error of some sort
|
|
HRESULT EnsureID(IWbemClassObject* pObj, WCHAR* pName)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
WCHAR* pKeyName = (pName == NULL) ? L"ID" : pName;
|
|
|
|
CComVariant
|
|
v;
|
|
|
|
if (SUCCEEDED(hr = pObj->Get(pKeyName, 0, &v, NULL, NULL)))
|
|
{
|
|
if ((v.vt == VT_NULL) || (v.bstrVal == NULL))
|
|
{
|
|
GUID guid;
|
|
|
|
CoCreateGuid(&guid);
|
|
|
|
BSTR guidStr = SysAllocStringByteLen(NULL, 129);
|
|
if (guidStr == NULL)
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
else
|
|
{
|
|
StringFromGUID2(guid, guidStr, 128);
|
|
|
|
VARIANT v;
|
|
VariantInit(&v);
|
|
v.vt = VT_BSTR;
|
|
v.bstrVal = guidStr;
|
|
|
|
pObj->Put(pKeyName, 0, &v, NULL);
|
|
|
|
SysFreeString(guidStr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
VariantClear(&v);
|
|
hr = WBEM_S_FALSE;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
void Init_AdsAttrInfo(ADS_ATTR_INFO *pAdsAttrInfo,
|
|
LPWSTR bstrName,
|
|
DWORD control,
|
|
ADSTYPE type,
|
|
PADSVALUE pVals,
|
|
DWORD nVals)
|
|
{
|
|
unsigned long c1;
|
|
|
|
if(NULL == pAdsAttrInfo) return;
|
|
|
|
pAdsAttrInfo->pszAttrName = bstrName;
|
|
pAdsAttrInfo->dwControlCode = control;
|
|
pAdsAttrInfo->dwADsType = type;
|
|
|
|
if(nVals > 0)
|
|
{
|
|
pAdsAttrInfo->dwNumValues = nVals;
|
|
|
|
if(NULL != pVals)
|
|
{
|
|
pAdsAttrInfo->pADsValues = pVals;
|
|
}
|
|
else
|
|
{
|
|
throw L"could not init ADS_ATTR_INFO structure";
|
|
}
|
|
|
|
for(c1 = 0; c1 < nVals; c1++)
|
|
{
|
|
(pAdsAttrInfo->pADsValues + c1)->dwType = type;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pAdsAttrInfo->dwNumValues = 0;
|
|
pAdsAttrInfo->pADsValues = NULL;
|
|
}
|
|
}
|
|
|
|
HRESULT DomainNameFromDistName(QString &DomainName, QString &DistName)
|
|
{
|
|
UINT
|
|
lDCStart = 0,
|
|
lDCEnd = 0;
|
|
|
|
while(QString::NOT_FOUND != DistName.NextPattern(lDCEnd, L"DC=", lDCStart))
|
|
{
|
|
if(QString::NOT_FOUND != DistName.NextChar(lDCStart, L",", lDCEnd))
|
|
DomainName.SubStrCat(DistName, lDCStart + 3, lDCEnd - 1) << L".";
|
|
else
|
|
{
|
|
lDCEnd = DistName.StringLength();
|
|
DomainName.SubStrCat(DistName, lDCStart + 3, lDCEnd);
|
|
}
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
HRESULT DistNameFromDomainName(QString &DomainName, QString &DistName)
|
|
{
|
|
if(0 == DomainName.StringLength())
|
|
return WBEM_E_FAILED;
|
|
|
|
UINT
|
|
lStart = 0,
|
|
lEnd = 0;
|
|
|
|
while(QString::NOT_FOUND != DomainName.NextChar(lStart, L".", lEnd))
|
|
{
|
|
if(lEnd)
|
|
{
|
|
DistName << L"DC=";
|
|
|
|
DistName.SubStrCat(DomainName, lStart, lEnd - 1);
|
|
lStart = lEnd + 1;
|
|
|
|
DistName << L",";
|
|
}
|
|
}
|
|
|
|
if(0 < lEnd)
|
|
{
|
|
DistName << L"DC=";
|
|
DistName.SubStrCat(DomainName, lStart, DomainName.StringLength());
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
IADsContainer *CreateContainer(BSTR bstrPath, BSTR bstrName)
|
|
{
|
|
HRESULT hres;
|
|
|
|
CComPtr<IDispatch>
|
|
pDisp;
|
|
|
|
CComPtr<IDirectoryObject>
|
|
pDirObj;
|
|
|
|
IADsContainer
|
|
*pADsContainer = NULL;
|
|
|
|
ADSVALUE
|
|
AdsValue[2];
|
|
|
|
ADS_ATTR_INFO
|
|
attrInfo[] =
|
|
{
|
|
{ g_bstrADObjectClass, ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, &AdsValue[0], 1},
|
|
{ L"ntSecurityDescriptor", ADS_ATTR_UPDATE, ADSTYPE_NT_SECURITY_DESCRIPTOR, &AdsValue[1], 1}
|
|
};
|
|
|
|
CNtSecurityDescriptor
|
|
cSD;
|
|
|
|
hres = CreateDefaultSecurityDescriptor(cSD);
|
|
|
|
if (FAILED(hres))
|
|
{
|
|
ERRORTRACE((LOG_ESS, "POLICMAN: could not create security descriptor\n"));
|
|
return NULL;
|
|
}
|
|
|
|
AdsValue[0].dwType = ADSTYPE_CASE_IGNORE_STRING;
|
|
AdsValue[0].CaseIgnoreString = L"Container";
|
|
|
|
AdsValue[1].dwType = ADSTYPE_NT_SECURITY_DESCRIPTOR;
|
|
AdsValue[1].SecurityDescriptor.dwLength = cSD.GetSize();
|
|
AdsValue[1].SecurityDescriptor.lpValue = (LPBYTE)cSD.GetPtr();
|
|
|
|
hres = ADsGetObject(bstrPath, IID_IDirectoryObject, (void**) &pDirObj);
|
|
if (FAILED(hres))
|
|
{
|
|
ERRORTRACE((LOG_ESS, "POLICMAN: (ADsGetObject) could not get AD object: %S, 0x%08X\n", bstrPath, hres));
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
hres = pDirObj->CreateDSObject(bstrName, attrInfo, 2, &pDisp);
|
|
if(FAILED(hres))
|
|
{
|
|
ERRORTRACE((LOG_ESS, "POLICMAN: could not create AD object: %S, 0x%08X\n", bstrName, hres));
|
|
return NULL;
|
|
}
|
|
|
|
hres = pDisp->QueryInterface(IID_IADsContainer, (void**)&pADsContainer);
|
|
}
|
|
|
|
return pADsContainer;
|
|
}
|
|
|
|
IADsContainer *CreateContainers(QString &pDomain, QString &pPath)
|
|
{
|
|
HRESULT
|
|
hres = WBEM_S_NO_ERROR;
|
|
|
|
CComVariant
|
|
v1;
|
|
|
|
IADsContainer
|
|
*pADsContainer_return = NULL;
|
|
|
|
CComPtr<IADsContainer>
|
|
pADsContainer,
|
|
pADsContainer2;
|
|
|
|
UINT
|
|
iIndex = 0,
|
|
iIndex2 = 0;
|
|
|
|
CComPtr<IDispatch>
|
|
pDisp;
|
|
|
|
// **** get root of domain
|
|
|
|
hres = ADsGetObject(QString(L"LDAP://") << pDomain, IID_IADsContainer, (void**)&pADsContainer);
|
|
if(FAILED(hres))
|
|
{
|
|
ERRORTRACE((LOG_ESS, "POLICMAN: (ADsGetObject) could not connect to domain %S, 0x%08X\n", pDomain, hres));
|
|
return NULL;
|
|
}
|
|
|
|
// **** find most derived element of pPath
|
|
|
|
while(QString::OK == pPath.NextPattern(iIndex, L"CN=", iIndex))
|
|
{
|
|
hres = pADsContainer->GetObject(NULL, &pPath[iIndex], &pDisp);
|
|
if(FAILED(hres) || (pDisp == NULL))
|
|
iIndex += 1;
|
|
else
|
|
break;
|
|
}
|
|
|
|
if(pDisp == NULL)
|
|
{
|
|
ERRORTRACE((LOG_ESS, "POLICMAN: (IADs::GetObject) could not get container %S\n", pDomain));
|
|
return NULL;
|
|
}
|
|
|
|
// **** now, backtrack up pPath creating each container as we go
|
|
|
|
while(QString::OK == pPath.PrevPattern(iIndex, L"CN=", iIndex))
|
|
{
|
|
if(NULL != pADsContainer_return)
|
|
pADsContainer_return->Release();
|
|
pADsContainer_return = NULL;
|
|
|
|
pPath.NextChar(iIndex, L",", iIndex2);
|
|
|
|
// **** isolate name to create
|
|
|
|
pPath[iIndex2] = L'\0';
|
|
pADsContainer_return = CreateContainer(QString(L"LDAP://") << &pPath[iIndex2 + 1] << L"," << pDomain, &pPath[iIndex]);
|
|
pPath[iIndex2] = L',';
|
|
|
|
if(pADsContainer_return == NULL)
|
|
{
|
|
ERRORTRACE((LOG_ESS, "POLICMAN: (ADsGetObject) could not get AD object: %S, 0x%08X\n", (wchar_t*)pPath, hres));
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return pADsContainer_return;
|
|
}
|
|
|
|
HRESULT ADSIToWMIErrorCodes(HRESULT hresAD)
|
|
{
|
|
if(((hresAD & 0x800FF000) == 0x80041000) ||
|
|
((hresAD & 0x800FF000) == 0x80042000) ||
|
|
((hresAD & 0x800FF000) == 0x80044000)) return hresAD;
|
|
|
|
if(hresAD != WBEM_S_NO_ERROR) switch(hresAD)
|
|
{
|
|
case S_ADS_ERRORSOCCURRED : return WBEM_E_FAILED ;
|
|
case S_ADS_NOMORE_ROWS : return WBEM_S_NO_MORE_DATA ;
|
|
case S_ADS_NOMORE_COLUMNS : return WBEM_S_NO_MORE_DATA ;
|
|
|
|
case E_ADS_UNKNOWN_OBJECT : return WBEM_E_NOT_FOUND ;
|
|
case E_ADS_OBJECT_EXISTS : return WBEM_E_ALREADY_EXISTS;
|
|
|
|
case 0x80070005 : return WBEM_E_ACCESS_DENIED; // LDAP_INSUFFICIENT_RIGHTS
|
|
case 0x80072030 : return WBEM_E_NOT_FOUND ; // LDAP_NO_SUCH_OBJECT
|
|
case 0x8007200a : return WBEM_E_FAILED; //LDAP_NO_SUCH_ATTRIBUTE
|
|
|
|
default : return WBEM_E_FAILED;
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
int IsEmpty(VARIANT &v)
|
|
{
|
|
if((v.vt == VT_NULL) || (v.vt == VT_EMPTY)) return 1;
|
|
|
|
if((v.vt == VT_UNKNOWN) || (v.vt == VT_DISPATCH))
|
|
{ if(NULL == v.punkVal)
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Creates the default security descriptor for WMI policy *containers*
|
|
// Full Control - Domain & Enterprise Admins & GPO Creator-Owner group
|
|
// Read Access - authenticated users
|
|
// assumes input pointer is NULL or uninitialized or some such
|
|
HRESULT CreateDefaultSecurityDescriptor(CNtSecurityDescriptor& cSD)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
CNtSid sidWorld(L"Authenticated Users");
|
|
|
|
CNtSid sidSystem(L"System");
|
|
CNtSid sidAdmins(L"Domain Admins");
|
|
CNtSid sidEnterpriseAdmins(L"Enterprise Admins");
|
|
CNtSid sidAdministrators(L"Administrators");
|
|
CNtSid sidGPO(L"Group Policy Creator Owners");
|
|
CNtSid sidOwner(L"CREATOR OWNER");
|
|
|
|
// hmmm - does six aces beat four aces?
|
|
// a smith and wesson beats four of a kind...
|
|
DWORD full = FULL_CONTROL | DS_GENERIC_ALL;
|
|
CNtAce aceEnterpriseAdmins(full, ACCESS_ALLOWED_ACE_TYPE, ADS_ACEFLAG_INHERIT_ACE, sidEnterpriseAdmins);
|
|
CNtAce aceOwner(full, ACCESS_ALLOWED_ACE_TYPE, ADS_ACEFLAG_INHERIT_ACE | ADS_ACEFLAG_INHERIT_ONLY_ACE, sidOwner);
|
|
CNtAce aceAdminsObject(full, ACCESS_ALLOWED_ACE_TYPE, ADS_ACEFLAG_INHERIT_ACE | ADS_ACEFLAG_INHERIT_ONLY_ACE, sidAdmins);
|
|
|
|
|
|
DWORD write = DS_GENERIC_READ | DS_GENERIC_WRITE | ACTRL_DS_CREATE_CHILD;
|
|
CNtAce aceAdmins(write | ACTRL_DS_DELETE_CHILD, ACCESS_ALLOWED_ACE_TYPE, 0, sidAdmins);
|
|
CNtAce aceAdministrators(write, ACCESS_ALLOWED_ACE_TYPE, 0, sidAdministrators);
|
|
CNtAce aceGPO(write, ACCESS_ALLOWED_ACE_TYPE, 0, sidGPO);
|
|
|
|
DWORD read = DS_GENERIC_READ;
|
|
CNtAce aceWorld(read, ACCESS_ALLOWED_ACE_TYPE, ADS_ACEFLAG_INHERIT_ACE, sidWorld);
|
|
CNtAce aceSystem(read, ACCESS_ALLOWED_ACE_TYPE, ADS_ACEFLAG_INHERIT_ACE, sidSystem);
|
|
|
|
CNtAcl ackl;
|
|
if (!ackl.AddAce(&aceWorld)) hr = WBEM_E_FAILED;
|
|
if (!ackl.AddAce(&aceSystem)) hr = WBEM_E_FAILED;
|
|
if (!ackl.AddAce(&aceAdmins)) hr = WBEM_E_FAILED;
|
|
if (!ackl.AddAce(&aceEnterpriseAdmins)) hr = WBEM_E_FAILED;
|
|
if (!ackl.AddAce(&aceAdministrators)) hr = WBEM_E_FAILED;
|
|
if (!ackl.AddAce(&aceGPO)) hr = WBEM_E_FAILED;
|
|
if (!ackl.AddAce(&aceOwner)) hr = WBEM_E_FAILED;
|
|
if (!ackl.AddAce(&aceAdminsObject)) hr = WBEM_E_FAILED;
|
|
|
|
if (!ackl.Resize(CNtAcl::MinimumSize)) hr = WBEM_E_FAILED;
|
|
|
|
if (!cSD.SetDacl(&ackl)) hr = WBEM_E_FAILED;
|
|
if (!cSD.SetOwner(&sidEnterpriseAdmins)) hr = WBEM_E_FAILED;
|
|
|
|
if (!SetSecurityDescriptorControl(cSD.GetPtr(), SE_DACL_PROTECTED, SE_DACL_PROTECTED)) hr = WBEM_E_FAILED;
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// given an input security descriptor
|
|
// add owner from thread
|
|
HRESULT GetOwnerSecurityDescriptor(CNtSecurityDescriptor& SD)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
CNtSid sidOwner(CNtSid::CURRENT_THREAD);
|
|
if (!SD.SetOwner(&sidOwner)) hr = WBEM_E_FAILED;
|
|
|
|
|
|
/***********************
|
|
CNtSid sidOwner(CNtSid::CURRENT_THREAD);
|
|
CNtAcl ackl;
|
|
|
|
if (!SD.GetDacl(ackl)) hr = WBEM_E_FAILED;
|
|
if (!SD.SetOwner(&sidOwner)) hr = WBEM_E_FAILED;
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CNtSid sidGPO(L"Group Policy Creator Owners");
|
|
|
|
int nAces = ackl.GetNumAces();
|
|
CNtAce* pAce = NULL;
|
|
CNtSid* pSid = NULL;
|
|
|
|
// walk through all the aces, find GPO owner creators & kill them
|
|
for (int i = 0; i < nAces; i++)
|
|
if ((pAce = ackl.GetAce(i)) && (pSid = pAce->GetSid()))
|
|
{
|
|
if ((*pSid == sidGPO) && (pAce->GetType() == ACCESS_ALLOWED_ACE_TYPE))
|
|
{
|
|
ackl.DeleteAce(i);
|
|
|
|
delete pAce;
|
|
delete pSid;
|
|
break;
|
|
}
|
|
|
|
delete pAce;
|
|
delete pSid;
|
|
}
|
|
else
|
|
//
|
|
{
|
|
hr = WBEM_E_CRITICAL_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CNtAce aceOwner(FULL_CONTROL, ACCESS_ALLOWED_ACE_TYPE, 0, sidOwner);
|
|
|
|
if (ackl.AddAce(&aceOwner) && SD.SetDacl(&ackl))
|
|
hr = WBEM_S_NO_ERROR;
|
|
else
|
|
hr = WBEM_E_FAILED;
|
|
|
|
|
|
}
|
|
******************/
|
|
|
|
return hr;
|
|
}
|
|
|
|
PSECURITY_DESCRIPTOR GetADSecurityDescriptor(IDirectoryObject *pIDirectoryObject)
|
|
{
|
|
HRESULT
|
|
hres;
|
|
|
|
LPWSTR
|
|
pAttrNames[] = { L"ntSecurityDescriptor" };
|
|
|
|
ADsStruct<ADS_ATTR_INFO>
|
|
pAttrInfo;
|
|
|
|
PSECURITY_DESCRIPTOR
|
|
pSD = NULL;
|
|
|
|
DWORD
|
|
dwReturn,
|
|
dwLength;
|
|
|
|
hres = pIDirectoryObject->GetObjectAttributes(pAttrNames, 1, &pAttrInfo, &dwReturn);
|
|
|
|
if(SUCCEEDED(hres) && (1 == dwReturn))
|
|
{
|
|
dwLength = pAttrInfo->pADsValues->SecurityDescriptor.dwLength;
|
|
|
|
pSD = new BYTE[dwLength];
|
|
if(NULL == pSD) return NULL;
|
|
|
|
ZeroMemory(pSD, dwLength);
|
|
|
|
memcpy(pSD, pAttrInfo->pADsValues->SecurityDescriptor.lpValue, dwLength);
|
|
}
|
|
|
|
return pSD;
|
|
}
|
|
|
|
HRESULT GetADContainerInDomain(wchar_t *wcsDomain, wchar_t *wcsPath, IDirectorySearch **pObj)
|
|
{
|
|
HRESULT
|
|
hres = WBEM_E_FAILED;
|
|
|
|
QString
|
|
DomainDistName,
|
|
LDAPPath(L"LDAP://");
|
|
|
|
// **** check args
|
|
|
|
if(NULL == pObj)
|
|
return WBEM_E_FAILED;
|
|
|
|
// **** build Path
|
|
|
|
hres = DistNameFromDomainName(QString(wcsDomain), DomainDistName);
|
|
|
|
LDAPPath << wcsPath << L"," << DomainDistName;
|
|
|
|
// **** attempt to connect to container in AD
|
|
|
|
hres = ADsGetObject(LDAPPath, IID_IDirectorySearch, (void**)pObj);
|
|
|
|
return ADSIToWMIErrorCodes(hres);
|
|
}
|
|
|
|
HRESULT ExecuteWQLQuery(wchar_t *wcsPath,
|
|
wchar_t *wcsWQLStmt,
|
|
IWbemObjectSink *pResponseHandler,
|
|
IWbemServices *pWbemServices,
|
|
BSTR bstrADClassName,
|
|
functTyp pf_ADToCIM)
|
|
{
|
|
HRESULT
|
|
hres = WBEM_E_FAILED;
|
|
|
|
int
|
|
nRes;
|
|
|
|
QL_LEVEL_1_TOKEN
|
|
*pToken = NULL;
|
|
|
|
CComPtr<IDirectorySearch>
|
|
pDirectorySearch;
|
|
|
|
QString
|
|
LDAPQuery;
|
|
|
|
wchar_t
|
|
objPath[1024];
|
|
|
|
ADS_SEARCH_HANDLE
|
|
searchHandle;
|
|
|
|
ADS_SEARCH_COLUMN
|
|
searchColumn;
|
|
|
|
wchar_t
|
|
*pszDistName[] = { L"distinguishedName" };
|
|
|
|
// **** parse WQL expression
|
|
|
|
CTextLexSource
|
|
src(wcsWQLStmt);
|
|
|
|
QL1_Parser
|
|
parser(&src);
|
|
|
|
QL_LEVEL_1_RPN_EXPRESSION
|
|
*pExp = NULL;
|
|
|
|
AutoDelete<QL_LEVEL_1_RPN_EXPRESSION>
|
|
AutoExp(&pExp);
|
|
|
|
if(nRes = parser.Parse(&pExp))
|
|
return WBEM_E_INVALID_QUERY;
|
|
|
|
// **** find domain attribute
|
|
|
|
for(int iToken = 0; (iToken < pExp->nNumTokens) && (NULL == pToken); iToken++)
|
|
{
|
|
pToken = &pExp->pArrayOfTokens[iToken];
|
|
|
|
if(_wcsicmp(g_bstrDomain, pToken->PropertyName.GetStringAt(pToken->PropertyName.GetNumElements() - 1)))
|
|
pToken = NULL;
|
|
}
|
|
|
|
if(NULL == pToken)
|
|
return WBEMESS_E_REGISTRATION_TOO_BROAD;
|
|
|
|
if((QL_LEVEL_1_TOKEN::OP_EXPRESSION != pToken->nTokenType) ||
|
|
(QL_LEVEL_1_TOKEN::OP_EQUAL != pToken->nOperator) ||
|
|
(TRUE == pToken->m_bPropComp) ||
|
|
(VT_BSTR != pToken->vConstValue.vt))
|
|
return WBEM_E_INVALID_QUERY;
|
|
|
|
if((NULL == bstrADClassName) || (NULL == pf_ADToCIM))
|
|
return WBEM_E_INVALID_QUERY;
|
|
|
|
// **** connect to LDAP location
|
|
|
|
hres = GetADContainerInDomain(pToken->vConstValue.bstrVal, wcsPath, &pDirectorySearch);
|
|
if(FAILED(hres))
|
|
{
|
|
if(WBEM_E_NOT_FOUND == hres)
|
|
return WBEM_S_NO_ERROR;
|
|
|
|
return hres;
|
|
}
|
|
else if(pDirectorySearch == NULL)
|
|
return WBEM_E_FAILED;
|
|
|
|
// **** build LDAP query to execute on container pADs
|
|
|
|
LDAPQuery << L"(objectCategory=" << bstrADClassName << L")";
|
|
|
|
// **** set search preferences
|
|
|
|
ADS_SEARCHPREF_INFO
|
|
SearchPreferences[1];
|
|
|
|
SearchPreferences[0].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
|
|
SearchPreferences[0].vValue.dwType = ADSTYPE_INTEGER;
|
|
SearchPreferences[0].vValue.Integer = 1000;
|
|
|
|
hres = pDirectorySearch->SetSearchPreference(SearchPreferences, 1);
|
|
|
|
if(FAILED(hres))
|
|
{
|
|
ERRORTRACE((LOG_ESS, "POLICMAN: Could not set search preferences, returned error: 0x%08X\n", (LPWSTR)LDAPQuery, hres));
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
// **** execute query
|
|
|
|
hres = pDirectorySearch->ExecuteSearch(LDAPQuery, pszDistName, 1, &searchHandle);
|
|
|
|
if(FAILED(hres))
|
|
{
|
|
ERRORTRACE((LOG_ESS, "POLICMAN: Could execute query: (%s) returned error: 0x%08X\n", (LPWSTR)LDAPQuery, hres));
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
// **** build result list
|
|
|
|
try
|
|
{
|
|
while(SUCCEEDED(hres = pDirectorySearch->GetNextRow(searchHandle)) && (S_ADS_NOMORE_ROWS != hres))
|
|
{
|
|
CComPtr<IDirectoryObject>
|
|
pDirectoryObject;
|
|
|
|
CComPtr<IWbemClassObject>
|
|
pWbemClassObject;
|
|
|
|
// **** get path to object
|
|
|
|
hres = pDirectorySearch->GetColumn(searchHandle, pszDistName[0], &searchColumn);
|
|
if(FAILED(hres)) return ADSIToWMIErrorCodes(hres);
|
|
|
|
// **** get pointer to object
|
|
|
|
wcscpy(objPath, L"LDAP://");
|
|
wcscat(objPath, searchColumn.pADsValues->CaseIgnoreString);
|
|
pDirectorySearch->FreeColumn(&searchColumn);
|
|
|
|
hres = ADsGetObject(objPath, IID_IDirectoryObject, (void **)&pDirectoryObject);
|
|
if(FAILED(hres)) return ADSIToWMIErrorCodes(hres);
|
|
|
|
hres = pf_ADToCIM(&pWbemClassObject, pDirectoryObject, pWbemServices);
|
|
if(FAILED(hres)) return ADSIToWMIErrorCodes(hres);
|
|
if(pWbemClassObject == NULL) return WBEM_E_FAILED;
|
|
|
|
hres = pResponseHandler->Indicate(1, &pWbemClassObject);
|
|
}
|
|
}
|
|
catch(long hret)
|
|
{
|
|
hres = ADSIToWMIErrorCodes(hret);
|
|
ERRORTRACE((LOG_ESS, "POLICMAN: Translation of Policy object from AD to WMI generated HRESULT 0x%08X\n", hres));
|
|
}
|
|
catch(wchar_t *swErrString)
|
|
{
|
|
ERRORTRACE((LOG_ESS, "POLICMAN: Caught Exception: %S\n", swErrString));
|
|
hres = WBEM_E_FAILED;
|
|
}
|
|
catch(...)
|
|
{
|
|
ERRORTRACE((LOG_ESS, "POLICMAN: Caught unknown Exception\n"));
|
|
hres = WBEM_E_TRANSPORT_FAILURE; // HACK for SP1
|
|
}
|
|
|
|
pDirectorySearch->CloseSearchHandle(searchHandle);
|
|
|
|
return hres;
|
|
}
|
|
|
|
void LogExtendedADErrorInfo(HRESULT hres)
|
|
{
|
|
DWORD dwLastError;
|
|
WCHAR szErrorBuf[1024], szNameBuf[256];
|
|
|
|
if(HRESULT_FACILITY(hres) == FACILITY_WIN32)
|
|
{
|
|
HRESULT hres2;
|
|
|
|
hres2 = ADsGetLastError(&dwLastError, szErrorBuf, 1023, szNameBuf, 255);
|
|
|
|
if(SUCCEEDED(hres2))
|
|
ERRORTRACE((LOG_ESS, "POLICMAN: Error Code: %d Error Text: %S Provider: %S\n", dwLastError, szErrorBuf, szNameBuf));
|
|
else
|
|
ERRORTRACE((LOG_ESS, "POLICMAN: Type mismatch on date property\n"));
|
|
}
|
|
}
|