1177 lines
25 KiB
C++
1177 lines
25 KiB
C++
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1995
|
|
//
|
|
// File: cdomain.cxx
|
|
//
|
|
// Contents: Windows NT 3.5
|
|
//
|
|
//
|
|
// History: 01-30-95 krishnag Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#include "winnt.hxx"
|
|
#pragma hdrstop
|
|
|
|
DECLARE_INFOLEVEL( Domain );
|
|
DECLARE_DEBUG( Domain );
|
|
#define DomainDebugOut(x) DomainInlineDebugOut x
|
|
|
|
// Class CWinNTDomain
|
|
|
|
DEFINE_IDispatch_ExtMgr_Implementation(CWinNTDomain)
|
|
DEFINE_IADsExtension_ExtMgr_Implementation(CWinNTDomain)
|
|
DEFINE_IADs_TempImplementation(CWinNTDomain)
|
|
DEFINE_IADs_PutGetImplementation(CWinNTDomain, DomainClass, gdwDomainTableSize)
|
|
DEFINE_IADsPropertyList_Implementation(CWinNTDomain, DomainClass, gdwDomainTableSize)
|
|
|
|
HRESULT
|
|
MoveUserGroupObject(
|
|
THIS_ BSTR SourceName,
|
|
BSTR NewName,
|
|
BSTR bstrParentADsPath,
|
|
CWinNTCredentials& Credentials,
|
|
IDispatch * FAR* ppObject
|
|
);
|
|
|
|
CWinNTDomain::CWinNTDomain() :
|
|
_pDispMgr(NULL),
|
|
_pExtMgr(NULL),
|
|
_pPropertyCache(NULL)
|
|
{
|
|
VariantInit(&_vFilter);
|
|
|
|
ENLIST_TRACKING(CWinNTDomain);
|
|
}
|
|
|
|
HRESULT
|
|
CWinNTDomain::CreateDomain(
|
|
BSTR Parent,
|
|
BSTR DomainName,
|
|
DWORD dwObjectState,
|
|
REFIID riid,
|
|
CWinNTCredentials& Credentials,
|
|
void **ppvObj
|
|
)
|
|
{
|
|
CWinNTDomain FAR * pDomain = NULL;
|
|
NET_API_STATUS nasStatus;
|
|
HRESULT hr = S_OK;
|
|
|
|
|
|
hr = AllocateDomainObject(&pDomain);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
ADsAssert(pDomain->_pDispMgr);
|
|
|
|
|
|
hr = pDomain->InitializeCoreObject(
|
|
Parent,
|
|
DomainName,
|
|
DOMAIN_CLASS_NAME,
|
|
DOMAIN_SCHEMA_NAME,
|
|
CLSID_WinNTDomain,
|
|
dwObjectState
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pDomain->_Credentials = Credentials;
|
|
hr = pDomain->_Credentials.RefDomain(DomainName);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
//
|
|
// Load ext mgr and extensions
|
|
//
|
|
|
|
hr = ADSILoadExtensionManager(
|
|
DOMAIN_CLASS_NAME,
|
|
(IADsDomain *) pDomain,
|
|
pDomain->_pDispMgr,
|
|
Credentials,
|
|
&pDomain->_pExtMgr
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
ADsAssert(pDomain->_pExtMgr);
|
|
|
|
// check if the call is from UMI
|
|
if(Credentials.GetFlags() & ADS_AUTH_RESERVED) {
|
|
//
|
|
// we do not pass riid to InitUmiObject below. This is because UMI object
|
|
// does not support IDispatch. There are several places in ADSI code where
|
|
// riid passed into this function is defaulted to IID_IDispatch -
|
|
// IADsContainer::Create for example. To handle these cases, we always
|
|
// request IID_IUnknown from the UMI object. Subsequent code within UMI
|
|
// will QI for the appropriate interface.
|
|
//
|
|
if(1 == pDomain->_dwNumComponents)
|
|
pDomain->_CompClasses[0] = L"Domain";
|
|
else
|
|
BAIL_ON_FAILURE(hr = UMI_E_FAIL);
|
|
|
|
hr = pDomain->InitUmiObject(
|
|
pDomain->_Credentials,
|
|
DomainClass,
|
|
gdwDomainTableSize,
|
|
pDomain->_pPropertyCache,
|
|
(IUnknown *) (INonDelegatingUnknown *) pDomain,
|
|
pDomain->_pExtMgr,
|
|
IID_IUnknown,
|
|
ppvObj
|
|
);
|
|
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// UMI object was created and the interface was obtained successfully.
|
|
// UMI object now has a reference to the inner unknown of IADs, since
|
|
// the call to Release() below is not going to be made in this case.
|
|
//
|
|
RRETURN(hr);
|
|
}
|
|
|
|
hr = pDomain->QueryInterface(riid, ppvObj);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pDomain->Release();
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
|
|
delete pDomain;
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
CWinNTDomain::~CWinNTDomain( )
|
|
{
|
|
VariantClear(&_vFilter);
|
|
|
|
delete _pExtMgr; // created last, destroyed first
|
|
|
|
delete _pDispMgr;
|
|
|
|
delete _pPropertyCache;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Function: QueryInterface
|
|
//
|
|
// Synopsis: If this object is aggregated within another object, then
|
|
// all calls will delegate to the outer object. Otherwise, the
|
|
// non-delegating QI is called
|
|
//
|
|
// Arguments:
|
|
//
|
|
// iid interface requested
|
|
// ppInterface Returns pointer to interface requested. NULL if interface
|
|
// is not supported.
|
|
//
|
|
// Returns: S_OK on success. Error code otherwise.
|
|
//
|
|
// Modifies: *ppInterface to return interface pointer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CWinNTDomain::QueryInterface(
|
|
REFIID iid,
|
|
LPVOID *ppInterface
|
|
)
|
|
{
|
|
if(_pUnkOuter != NULL)
|
|
RRETURN(_pUnkOuter->QueryInterface(
|
|
iid,
|
|
ppInterface
|
|
));
|
|
|
|
RRETURN(NonDelegatingQueryInterface(
|
|
iid,
|
|
ppInterface
|
|
));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Function: AddRef
|
|
//
|
|
// Synopsis: IUnknown::AddRef. If this object is aggregated within
|
|
// another, all calls will delegate to the outer object.
|
|
// Otherwise, the non-delegating AddRef is called
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None
|
|
//
|
|
// Returns: New reference count
|
|
//
|
|
// Modifies: Nothing
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CWinNTDomain::AddRef(void)
|
|
{
|
|
if(_pUnkOuter != NULL)
|
|
RRETURN(_pUnkOuter->AddRef());
|
|
|
|
RRETURN(NonDelegatingAddRef());
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Function: Release
|
|
//
|
|
// Synopsis: IUnknown::Release. If this object is aggregated within
|
|
// another, all calls will delegate to the outer object.
|
|
// Otherwise, the non-delegating Release is called
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None
|
|
//
|
|
// Returns: New reference count
|
|
//
|
|
// Modifies: Nothing
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CWinNTDomain::Release(void)
|
|
{
|
|
if(_pUnkOuter != NULL)
|
|
RRETURN(_pUnkOuter->Release());
|
|
|
|
RRETURN(NonDelegatingRelease());
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CWinNTDomain::NonDelegatingQueryInterface(
|
|
REFIID iid,
|
|
LPVOID FAR* ppv
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (ppv == NULL) {
|
|
RRETURN(E_POINTER);
|
|
}
|
|
|
|
if (IsEqualIID(iid, IID_IUnknown))
|
|
{
|
|
*ppv = (IADsDomain FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IADsDomain))
|
|
{
|
|
*ppv = (IADsDomain FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IADsContainer))
|
|
{
|
|
*ppv = (IADsContainer FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IADs))
|
|
{
|
|
*ppv = (IADs FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IADsPropertyList))
|
|
{
|
|
*ppv = (IADsPropertyList FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IDispatch))
|
|
{
|
|
*ppv = (IADs FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_ISupportErrorInfo))
|
|
{
|
|
*ppv = (ISupportErrorInfo FAR *) this;
|
|
}
|
|
else if( (_pDispatch != NULL) &&
|
|
IsEqualIID(iid, IID_IADsExtension) )
|
|
{
|
|
*ppv = (IADsExtension *) this;
|
|
}
|
|
else if (_pExtMgr)
|
|
{
|
|
RRETURN( _pExtMgr->QueryInterface(iid, ppv));
|
|
}
|
|
else
|
|
{
|
|
*ppv = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
/* ISupportErrorInfo method */
|
|
STDMETHODIMP
|
|
CWinNTDomain::InterfaceSupportsErrorInfo(
|
|
THIS_ REFIID riid
|
|
)
|
|
{
|
|
if (IsEqualIID(riid, IID_IADs) ||
|
|
IsEqualIID(riid, IID_IADsContainer) ||
|
|
IsEqualIID(riid, IID_IADsPropertyList) ||
|
|
IsEqualIID(riid, IID_IADsDomain)) {
|
|
RRETURN(S_OK);
|
|
} else {
|
|
RRETURN(S_FALSE);
|
|
}
|
|
}
|
|
STDMETHODIMP
|
|
CWinNTDomain::SetInfo(THIS)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = SetInfo(0);
|
|
|
|
hr = SetInfo(2);
|
|
|
|
hr = SetInfo(3);
|
|
|
|
if(SUCCEEDED(hr))
|
|
_pPropertyCache->ClearModifiedFlags();
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTDomain::GetInfo(THIS)
|
|
{
|
|
HRESULT hr;
|
|
|
|
_pPropertyCache->flushpropcache();
|
|
|
|
hr = GetInfo(0, TRUE);
|
|
|
|
hr = GetInfo(2, TRUE);
|
|
|
|
hr = GetInfo(3, TRUE);
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTDomain::ImplicitGetInfo(THIS)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = GetInfo(0, FALSE);
|
|
|
|
hr = GetInfo(2, FALSE);
|
|
|
|
hr = GetInfo(3, FALSE);
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
/* IADsContainer methods */
|
|
|
|
STDMETHODIMP
|
|
CWinNTDomain::get_Count(long FAR* retval)
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTDomain::get_Filter(THIS_ VARIANT FAR* pVar)
|
|
{
|
|
HRESULT hr;
|
|
VariantInit(pVar);
|
|
hr = VariantCopy(pVar, &_vFilter);
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTDomain::put_Filter(THIS_ VARIANT Var)
|
|
{
|
|
HRESULT hr;
|
|
hr = VariantCopy(&_vFilter, &Var);
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTDomain::put_Hints(THIS_ VARIANT Var)
|
|
{
|
|
RRETURN_EXP_IF_ERR( E_NOTIMPL);
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CWinNTDomain::get_Hints(THIS_ VARIANT FAR* pVar)
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTDomain::GetObject(
|
|
THIS_ BSTR ClassName,
|
|
BSTR RelativeName,
|
|
IDispatch * FAR* ppObject
|
|
)
|
|
{
|
|
|
|
WCHAR szBuffer[MAX_PATH];
|
|
DWORD dwLength = 0;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!RelativeName || !*RelativeName) {
|
|
RRETURN_EXP_IF_ERR(E_ADS_UNKNOWN_OBJECT);
|
|
}
|
|
|
|
//
|
|
// Verify that the lenght of the string will not cause overflow.
|
|
// +2 for / and \0
|
|
//
|
|
dwLength = wcslen(_ADsPath) + wcslen(RelativeName) + 2;
|
|
if (dwLength > MAX_PATH) {
|
|
BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
|
|
}
|
|
|
|
wcscpy(szBuffer, _ADsPath);
|
|
|
|
wcscat(szBuffer, L"/");
|
|
wcscat(szBuffer, RelativeName);
|
|
|
|
if (ClassName) {
|
|
//
|
|
// +1 for the ",".
|
|
//
|
|
dwLength += wcslen(ClassName) + 1;
|
|
//
|
|
// Check for buffer overflow again.
|
|
//
|
|
if (dwLength > MAX_PATH) {
|
|
BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
|
|
}
|
|
wcscat(szBuffer,L",");
|
|
wcscat(szBuffer, ClassName);
|
|
}
|
|
|
|
hr = ::GetObject(
|
|
szBuffer,
|
|
(LPVOID *)ppObject,
|
|
_Credentials
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
error:
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTDomain::get__NewEnum(
|
|
THIS_ IUnknown * FAR* retval
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
IUnknown FAR* punkEnum=NULL;
|
|
IEnumVARIANT * penum = NULL;
|
|
|
|
|
|
*retval = NULL;
|
|
|
|
hr = CWinNTDomainEnum::Create(
|
|
(CWinNTDomainEnum **)&penum,
|
|
_ADsPath,
|
|
_Name,
|
|
_vFilter,
|
|
_Credentials
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = penum->QueryInterface(
|
|
IID_IUnknown,
|
|
(VOID FAR* FAR*)retval
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
if (penum) {
|
|
penum->Release();
|
|
}
|
|
|
|
RRETURN(NOERROR);
|
|
|
|
error:
|
|
|
|
if (penum) {
|
|
delete penum;
|
|
}
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CWinNTDomain::Create(
|
|
THIS_ BSTR ClassName,
|
|
BSTR RelativeName,
|
|
IDispatch * FAR* ppObject
|
|
)
|
|
{
|
|
ULONG ObjectType = 0;
|
|
HRESULT hr;
|
|
POBJECTINFO pObjectInfo = NULL;
|
|
|
|
hr = GetObjectType(
|
|
gpFilters,
|
|
gdwMaxFilters,
|
|
ClassName,
|
|
(PDWORD)&ObjectType
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
switch (ObjectType) {
|
|
|
|
case WINNT_USER_ID:
|
|
|
|
hr = CWinNTUser::CreateUser(
|
|
_ADsPath,
|
|
WINNT_DOMAIN_ID,
|
|
_Name,
|
|
NULL,
|
|
RelativeName,
|
|
ADS_OBJECT_UNBOUND,
|
|
IID_IDispatch,
|
|
_Credentials,
|
|
(void **)ppObject
|
|
);
|
|
break;
|
|
|
|
case WINNT_GROUP_ID:
|
|
hr = CWinNTGroup::CreateGroup(
|
|
_ADsPath,
|
|
WINNT_DOMAIN_ID,
|
|
_Name,
|
|
NULL,
|
|
RelativeName,
|
|
WINNT_GROUP_GLOBAL,
|
|
ADS_OBJECT_UNBOUND,
|
|
IID_IDispatch,
|
|
_Credentials,
|
|
(void **)ppObject
|
|
);
|
|
break;
|
|
|
|
case WINNT_COMPUTER_ID:
|
|
hr = CWinNTComputer::CreateComputer(
|
|
_ADsPath,
|
|
_Name,
|
|
RelativeName,
|
|
ADS_OBJECT_UNBOUND,
|
|
IID_IDispatch,
|
|
_Credentials,
|
|
(void **)ppObject
|
|
);
|
|
break;
|
|
|
|
default:
|
|
|
|
hr = E_ADS_UNKNOWN_OBJECT;
|
|
break;
|
|
}
|
|
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
error:
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTDomain::Delete(
|
|
BSTR bstrClassName,
|
|
BSTR bstrSourceName
|
|
)
|
|
{
|
|
ULONG ObjectType = 0;
|
|
POBJECTINFO pObjectInfo = NULL;
|
|
BOOL fStatus = FALSE;
|
|
HRESULT hr = S_OK;
|
|
WCHAR szUncServerName[MAX_PATH];
|
|
|
|
|
|
// Make sure input parameters are valid
|
|
if (bstrClassName == NULL || bstrSourceName == NULL) {
|
|
BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
|
|
}
|
|
|
|
|
|
hr = GetObjectType(gpFilters,
|
|
gdwMaxFilters,
|
|
bstrClassName,
|
|
(PDWORD)&ObjectType
|
|
);
|
|
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
hr = BuildObjectInfo(
|
|
_ADsPath,
|
|
bstrSourceName,
|
|
&pObjectInfo
|
|
);
|
|
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
switch (ObjectType) {
|
|
|
|
case WINNT_USER_ID:
|
|
|
|
hr = WinNTDeleteUser(pObjectInfo, _Credentials);
|
|
break;
|
|
|
|
case WINNT_GROUP_ID:
|
|
|
|
//
|
|
// for backward compatablity: allow user to delete by classname "group"
|
|
//
|
|
|
|
hr = WinNTDeleteGroup(pObjectInfo, WINNT_GROUP_EITHER, _Credentials);
|
|
break;
|
|
|
|
//
|
|
// Global Group and LocalGroup ID's will now goto default
|
|
//
|
|
|
|
case WINNT_COMPUTER_ID:
|
|
|
|
hr = WinNTDeleteComputer(pObjectInfo, _Credentials);
|
|
break;
|
|
|
|
default:
|
|
|
|
hr = E_ADS_UNKNOWN_OBJECT;
|
|
break;
|
|
}
|
|
|
|
error:
|
|
|
|
if (pObjectInfo) {
|
|
FreeObjectInfo(pObjectInfo);
|
|
}
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CWinNTDomain::CopyHere(
|
|
THIS_ BSTR SourceName,
|
|
BSTR NewName,
|
|
IDispatch * FAR* ppObject
|
|
)
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTDomain::MoveHere(
|
|
THIS_ BSTR SourceName,
|
|
BSTR NewName,
|
|
IDispatch * FAR* ppObject
|
|
)
|
|
{
|
|
return MoveUserGroupObject(SourceName,
|
|
NewName,
|
|
_ADsPath,
|
|
_Credentials,
|
|
ppObject);
|
|
}
|
|
|
|
/* IADsDomain methods */
|
|
|
|
STDMETHODIMP
|
|
CWinNTDomain::get_IsWorkgroup(THIS_ VARIANT_BOOL FAR* retval)
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_NOTIMPL);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CWinNTDomain::AllocateDomainObject(
|
|
CWinNTDomain ** ppDomain
|
|
)
|
|
{
|
|
CWinNTDomain FAR * pDomain = NULL;
|
|
CAggregatorDispMgr FAR * pDispMgr = NULL;
|
|
CPropertyCache FAR * pPropertyCache = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
pDomain = new CWinNTDomain();
|
|
if (pDomain == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
pDispMgr = new CAggregatorDispMgr;
|
|
if (pDispMgr == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = LoadTypeInfoEntry(
|
|
pDispMgr,
|
|
LIBID_ADs,
|
|
IID_IADsDomain,
|
|
(IADsDomain *)pDomain,
|
|
DISPID_REGULAR
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = LoadTypeInfoEntry(
|
|
pDispMgr,
|
|
LIBID_ADs,
|
|
IID_IADsContainer,
|
|
(IADsContainer *)pDomain,
|
|
DISPID_NEWENUM
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
hr = LoadTypeInfoEntry(
|
|
pDispMgr,
|
|
LIBID_ADs,
|
|
IID_IADsPropertyList,
|
|
(IADsPropertyList *)pDomain,
|
|
DISPID_VALUE
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
hr = CPropertyCache::createpropertycache(
|
|
DomainClass,
|
|
gdwDomainTableSize,
|
|
(CCoreADsObject *)pDomain,
|
|
&pPropertyCache
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
pDispMgr->RegisterPropertyCache(
|
|
pPropertyCache
|
|
);
|
|
|
|
|
|
pDomain->_pPropertyCache = pPropertyCache;
|
|
pDomain->_pDispMgr = pDispMgr;
|
|
*ppDomain = pDomain;
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
|
|
delete pPropertyCache;
|
|
delete pDispMgr;
|
|
delete pDomain;
|
|
|
|
RRETURN(hr);
|
|
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CWinNTDomain::GetInfo(
|
|
THIS_ DWORD dwApiLevel,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
NET_API_STATUS nasStatus;
|
|
LPBYTE lpBuffer = NULL;
|
|
HRESULT hr;
|
|
WCHAR szPDCName[MAX_PATH];
|
|
|
|
hr = WinNTGetCachedDCName(
|
|
_Name,
|
|
szPDCName,
|
|
_Credentials.GetFlags()
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
nasStatus = NetUserModalsGet(
|
|
szPDCName,
|
|
dwApiLevel,
|
|
&lpBuffer
|
|
);
|
|
hr = HRESULT_FROM_WIN32(nasStatus);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = UnMarshall(lpBuffer, dwApiLevel, fExplicit);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
error:
|
|
if (lpBuffer) {
|
|
NetApiBufferFree(lpBuffer);
|
|
}
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CWinNTDomain::UnMarshall(
|
|
LPBYTE lpBuffer,
|
|
DWORD dwApiLevel,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
ADsAssert(lpBuffer);
|
|
switch (dwApiLevel) {
|
|
case 0:
|
|
hr = UnMarshall_Level0(fExplicit, (LPUSER_MODALS_INFO_0)lpBuffer);
|
|
break;
|
|
|
|
case 2:
|
|
hr = UnMarshall_Level2(fExplicit, (LPUSER_MODALS_INFO_2)lpBuffer);
|
|
break;
|
|
|
|
|
|
case 3:
|
|
hr = UnMarshall_Level3(fExplicit, (LPUSER_MODALS_INFO_3)lpBuffer);
|
|
break;
|
|
|
|
default:
|
|
hr = E_FAIL;
|
|
|
|
}
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CWinNTDomain::UnMarshall_Level0(
|
|
BOOL fExplicit,
|
|
LPUSER_MODALS_INFO_0 pUserInfo0
|
|
)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = SetDWORDPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("MinPasswordLength"),
|
|
pUserInfo0->usrmod0_min_passwd_len,
|
|
fExplicit
|
|
);
|
|
|
|
hr = SetDWORDPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("MaxPasswordAge"),
|
|
pUserInfo0->usrmod0_max_passwd_age,
|
|
fExplicit
|
|
);
|
|
|
|
|
|
hr = SetDWORDPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("MinPasswordAge"),
|
|
pUserInfo0->usrmod0_min_passwd_age,
|
|
fExplicit
|
|
);
|
|
|
|
|
|
hr = SetDWORDPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("PasswordHistoryLength"),
|
|
pUserInfo0->usrmod0_password_hist_len,
|
|
fExplicit
|
|
);
|
|
|
|
hr = SetLPTSTRPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("Name"),
|
|
_Name,
|
|
fExplicit
|
|
);
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CWinNTDomain::UnMarshall_Level2(
|
|
BOOL fExplicit,
|
|
LPUSER_MODALS_INFO_2 pUserInfo2
|
|
)
|
|
{
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CWinNTDomain::UnMarshall_Level3(
|
|
BOOL fExplicit,
|
|
LPUSER_MODALS_INFO_3 pUserInfo3
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = SetDWORDPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("AutoUnlockInterval"),
|
|
pUserInfo3->usrmod3_lockout_duration,
|
|
fExplicit
|
|
);
|
|
|
|
hr = SetDWORDPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("LockoutObservationInterval"),
|
|
pUserInfo3->usrmod3_lockout_observation_window,
|
|
fExplicit
|
|
);
|
|
|
|
hr = SetDWORDPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("MaxBadPasswordsAllowed"),
|
|
pUserInfo3->usrmod3_lockout_threshold,
|
|
fExplicit
|
|
);
|
|
|
|
RRETURN_EXP_IF_ERR(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTDomain::SetInfo(THIS_ DWORD dwApiLevel)
|
|
{
|
|
NET_API_STATUS nasStatus;
|
|
HRESULT hr;
|
|
LPBYTE lpBuffer = NULL;
|
|
DWORD dwParamErr = 0;
|
|
WCHAR szPDCName[MAX_PATH];
|
|
|
|
|
|
hr = WinNTGetCachedDCName(
|
|
_Name,
|
|
szPDCName,
|
|
_Credentials.GetFlags()
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
nasStatus = NetUserModalsGet(
|
|
szPDCName,
|
|
dwApiLevel,
|
|
&lpBuffer
|
|
);
|
|
hr = HRESULT_FROM_WIN32(nasStatus);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
|
|
hr = MarshallAndSet(szPDCName, lpBuffer, dwApiLevel);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
error:
|
|
|
|
if (lpBuffer) {
|
|
NetApiBufferFree(lpBuffer);
|
|
}
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CWinNTDomain::MarshallAndSet(
|
|
LPWSTR szServerName,
|
|
LPBYTE lpBuffer,
|
|
DWORD dwApiLevel
|
|
)
|
|
{
|
|
ADsAssert(lpBuffer);
|
|
switch (dwApiLevel) {
|
|
case 0:
|
|
RRETURN(Marshall_Set_Level0(
|
|
szServerName,
|
|
(LPUSER_MODALS_INFO_0)lpBuffer
|
|
));
|
|
break;
|
|
|
|
case 2:
|
|
RRETURN(Marshall_Set_Level2(
|
|
szServerName,
|
|
(LPUSER_MODALS_INFO_2)lpBuffer
|
|
));
|
|
break;
|
|
|
|
|
|
case 3:
|
|
RRETURN(Marshall_Set_Level3(
|
|
szServerName,
|
|
(LPUSER_MODALS_INFO_3)lpBuffer
|
|
));
|
|
break;
|
|
|
|
default:
|
|
RRETURN(E_FAIL);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CWinNTDomain::Marshall_Set_Level0(
|
|
LPWSTR szServerName,
|
|
LPUSER_MODALS_INFO_0 pUserInfo0)
|
|
{
|
|
NET_API_STATUS nasStatus;
|
|
DWORD dwParamErr = 0;
|
|
HRESULT hr = S_OK;
|
|
|
|
DWORD dwMinPasswdLen = 0;
|
|
DWORD dwMaxPasswdAge = 0;
|
|
DWORD dwMinPasswdAge = 0;
|
|
DWORD dwPasswdHistLen = 0;
|
|
|
|
hr = GetDWORDPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("MinPasswordLength"),
|
|
&dwMinPasswdLen
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
pUserInfo0->usrmod0_min_passwd_len = dwMinPasswdLen;
|
|
}
|
|
|
|
hr = GetDWORDPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("MaxPasswordAge"),
|
|
&dwMaxPasswdAge
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
pUserInfo0->usrmod0_max_passwd_age = dwMaxPasswdAge;
|
|
}
|
|
|
|
|
|
hr = GetDWORDPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("MinPasswordAge"),
|
|
&dwMinPasswdAge
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
pUserInfo0->usrmod0_min_passwd_age = dwMinPasswdAge;
|
|
}
|
|
|
|
|
|
hr = GetDWORDPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("PasswordHistoryLength"),
|
|
&dwPasswdHistLen
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
pUserInfo0->usrmod0_password_hist_len = dwPasswdHistLen;
|
|
}
|
|
|
|
//
|
|
// Now Set this Data. Remember that the property store
|
|
// returns to us data in its own format. It is the caller's
|
|
// responsibility to free all buffers for bstrs, variants
|
|
// etc
|
|
//
|
|
|
|
nasStatus = NetUserModalsSet(
|
|
szServerName,
|
|
0,
|
|
(LPBYTE)pUserInfo0,
|
|
&dwParamErr
|
|
);
|
|
hr = HRESULT_FROM_WIN32(nasStatus);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
error:
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CWinNTDomain::Marshall_Set_Level2(
|
|
LPWSTR szServerName,
|
|
LPUSER_MODALS_INFO_2 pUserInfo2
|
|
)
|
|
{
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CWinNTDomain::Marshall_Set_Level3(
|
|
LPWSTR szServerName,
|
|
LPUSER_MODALS_INFO_3 pUserInfo3
|
|
)
|
|
{
|
|
NET_API_STATUS nasStatus;
|
|
HRESULT hr;
|
|
DWORD dwParamErr = 0;
|
|
|
|
DWORD dwAutoUnlockIntrvl = 0;
|
|
DWORD dwLockoutObsIntrvl = 0;
|
|
DWORD dwMaxBadPasswdsAllowed = 0;
|
|
|
|
hr = GetDWORDPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("AutoUnlockInterval"),
|
|
&dwAutoUnlockIntrvl
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
pUserInfo3->usrmod3_lockout_duration = dwAutoUnlockIntrvl;
|
|
}
|
|
|
|
hr = GetDWORDPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("LockoutObservationInterval"),
|
|
&dwLockoutObsIntrvl
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
pUserInfo3->usrmod3_lockout_observation_window = dwLockoutObsIntrvl;
|
|
}
|
|
|
|
|
|
hr = GetDWORDPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("MaxBadPasswordsAllowed"),
|
|
&dwMaxBadPasswdsAllowed
|
|
);
|
|
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
pUserInfo3->usrmod3_lockout_threshold = dwMaxBadPasswdsAllowed;
|
|
}
|
|
|
|
|
|
//
|
|
// Now Set this Data. Remember that the property store
|
|
// returns to us data in its own format. It is the caller's
|
|
// responsibility to free all buffers for bstrs, variants
|
|
// etc
|
|
//
|
|
|
|
nasStatus = NetUserModalsSet(
|
|
szServerName,
|
|
3,
|
|
(LPBYTE)pUserInfo3,
|
|
&dwParamErr
|
|
);
|
|
hr = HRESULT_FROM_WIN32(nasStatus);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
error:
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|