WindowsXP-SP1/ds/adsi/msext/cdomain.cxx
2020-09-30 16:53:49 +02:00

1024 lines
23 KiB
C++

krishna says this file should be removed
//---------------------------------------------------------------------------
//
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996
//
// File: cdomain.cxx
//
// Contents: Windows NT 3.5
//
//
// History: 09-23-96 yihsins Created.
//
//----------------------------------------------------------------------------
#include "ldap.hxx"
#pragma hdrstop
DECLARE_INFOLEVEL( Domain );
DECLARE_DEBUG( Domain );
#define DomainDebugOut(x) DomainInlineDebugOut x
struct _propmap
{
LPTSTR pszADsProp;
LPTSTR pszLDAPProp;
} aDomainPropMapping[] =
{ { TEXT("MinPasswordLength"), TEXT("minPwdLength") },
{ TEXT("MinPasswordAge"), TEXT("minPwdAge") },
{ TEXT("MaxPasswordAge"), TEXT("maxPwdAge") },
{ TEXT("MaxBadPasswordsAllowed"), TEXT("lockoutThreshold") },
{ TEXT("PasswordHistoryLength"), TEXT("pwdHistoryLength") },
{ TEXT("PasswordAttributes"), TEXT("pwdProperties") },
{ TEXT("AutoUnlockInterval"), TEXT("lockoutDuration") },
{ TEXT("LockoutObservationInterval"), TEXT("lockOutObservationWindow") },
// { TEXT("IsWorkgroup"), TEXT("IsWorkgroup") }, // ???
};
//
// Class CLDAPDomain
//
DEFINE_IDispatch_Implementation(CLDAPDomain)
DEFINE_CONTAINED_IADs_Implementation(CLDAPDomain)
DEFINE_CONTAINED_IADsContainer_Implementation(CLDAPDomain)
DEFINE_CONTAINED_IDirectoryObject_Implementation(CLDAPDomain)
DEFINE_CONTAINED_IDirectorySearch_Implementation(CLDAPDomain)
DEFINE_CONTAINED_IDirectorySchemaMgmt_Implementation(CLDAPDomain)
DEFINE_CONTAINED_IADsPutGet_Implementation(CLDAPDomain, aDomainPropMapping)
DEFINE_CONTAINED_IADsPropertyList_Implementation(CLDAPDomain)
CLDAPDomain::CLDAPDomain()
: _pADs(NULL),
_pADsContainer(NULL),
_pDSObject(NULL),
_pDSSearch(NULL),
_pDispMgr(NULL),
_pDSSchMgmt(NULL),
_pADsPropList(NULL)
{
ENLIST_TRACKING(CLDAPDomain);
}
HRESULT
CLDAPDomain::CreateDomain(
IADs *pADs,
REFIID riid,
void **ppvObj
)
{
CLDAPDomain FAR * pDomain = NULL;
HRESULT hr = S_OK;
hr = AllocateDomainObject( pADs, &pDomain);
BAIL_ON_FAILURE(hr);
hr = pDomain->QueryInterface( riid, ppvObj);
BAIL_ON_FAILURE(hr);
pDomain->Release();
RRETURN(hr);
error:
*ppvObj = NULL;
delete pDomain;
RRETURN(hr);
}
CLDAPDomain::~CLDAPDomain( )
{
if ( _pADs )
_pADs->Release();
if ( _pADsContainer )
_pADsContainer->Release();
if ( _pDSObject )
_pDSObject->Release();
if ( _pDSSearch )
_pDSSearch->Release();
if ( _pDSSchMgmt )
_pDSSchMgmt->Release();
if (_pADsPropList) {
_pADsPropList->Release();
}
delete _pDispMgr;
}
STDMETHODIMP
CLDAPDomain::QueryInterface(
REFIID iid,
LPVOID FAR* ppv
)
{
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) && _pADsContainer )
{
*ppv = (IADsContainer FAR *) this;
}
else if (IsEqualIID(iid, IID_IDirectoryObject) && _pDSObject )
{
*ppv = (IDirectoryObject FAR *) this;
}
else if (IsEqualIID(iid, IID_IDirectorySearch) && _pDSSearch )
{
*ppv = (IDirectorySearch FAR *) this;
}
else if (IsEqualIID(iid, IID_IDirectorySchemaMgmt) && _pDSSchMgmt )
{
*ppv = (IDirectorySchemaMgmt FAR *) this;
}
else if (IsEqualIID(iid, IID_IADsPropertyList) && _pADsPropList )
{
*ppv = (IADsPropertyList FAR *) this;
}
else if (IsEqualIID(iid, IID_IADs))
{
*ppv = (IADs FAR *) this;
}
else if (IsEqualIID(iid, IID_IDispatch))
{
*ppv = (IADs FAR *) this;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
HRESULT
CLDAPDomain::AllocateDomainObject(
IADs *pADs,
CLDAPDomain **ppDomain
)
{
CLDAPDomain FAR * pDomain = NULL;
CAggregateeDispMgr FAR * pDispMgr = NULL;
HRESULT hr = S_OK;
IADsContainer FAR * pADsContainer = NULL;
IDirectoryObject FAR * pDSObject = NULL;
IDirectorySearch FAR * pDSSearch= NULL;
IDirectorySchemaMgmt FAR * pDSSchMgmt= NULL;
IADsPropertyList FAR * pADsPropList = NULL;
IDispatch *pDispatch = NULL;
pDomain = new CLDAPDomain();
if (pDomain == NULL) {
hr = E_OUTOFMEMORY;
}
BAIL_ON_FAILURE(hr);
pDispMgr = new CAggregateeDispMgr;
if (pDispMgr == NULL) {
hr = E_OUTOFMEMORY;
}
BAIL_ON_FAILURE(hr);
hr = pDispMgr->LoadTypeInfoEntry(
LIBID_ADs,
IID_IADsDomain,
(IADsDomain *)pDomain,
DISPID_REGULAR
);
BAIL_ON_FAILURE(hr);
hr = pDispMgr->LoadTypeInfoEntry(
LIBID_ADs,
IID_IADsContainer,
(IADsContainer *)pDomain,
DISPID_NEWENUM
);
BAIL_ON_FAILURE(hr);
hr = pDispMgr->LoadTypeInfoEntry(
LIBID_ADs,
IID_IADsPropertyList,
(IADsPropertyList *)pADsPropList,
DISPID_VALUE
);
BAIL_ON_FAILURE(hr);
hr = pADs->QueryInterface(IID_IDispatch, (void **)&pDispatch);
BAIL_ON_FAILURE(hr);
pDispMgr->RegisterBaseDispatchPtr(pDispatch);
//
// Store a pointer to the Container interface
//
hr = pADs->QueryInterface(
IID_IADsContainer,
(void **)&pADsContainer
);
BAIL_ON_FAILURE(hr);
pDomain->_pADsContainer = pADsContainer;
//
// Store a pointer to the DSObject interface
//
hr = pADs->QueryInterface(
IID_IDirectoryObject,
(void **)&pDSObject
);
BAIL_ON_FAILURE(hr);
pDomain->_pDSObject = pDSObject;
//
// Store a pointer to the DSSearch interface
//
hr = pADs->QueryInterface(
IID_IDirectorySearch,
(void **)&pDSSearch
);
BAIL_ON_FAILURE(hr);
pDomain->_pDSSearch= pDSSearch;
hr = pADs->QueryInterface(
IID_IADsPropertyList,
(void **)&pADsPropList
);
BAIL_ON_FAILURE(hr);
pDomain->_pADsPropList = pADsPropList;
//
// Store a pointer to the DSSchMgmt interface
//
hr = pADs->QueryInterface(
IID_IDirectorySchemaMgmt,
(void **)&pDSSchMgmt
);
BAIL_ON_FAILURE(hr);
pDomain->_pDSSchMgmt= pDSSchMgmt;
//
// Store the pointer to the internal generic object
// AND add ref this pointer
//
pDomain->_pADs = pADs;
pADs->AddRef();
pDomain->_pDispMgr = pDispMgr;
*ppDomain = pDomain;
RRETURN(hr);
error:
delete pDispMgr;
delete pDomain;
RRETURN(hr);
}
/* IADsContainer methods */
#if 0
STDMETHODIMP
CLDAPDomain::get__NewEnum(
THIS_ IUnknown * FAR* retval
)
{
HRESULT hr;
IUnknown FAR* punkEnum=NULL;
IEnumVARIANT * penum = NULL;
*retval = NULL;
hr = CLDAPDomainEnum::Create(
(CLDAPDomainEnum **)&penum,
_ADsPath,
_Name,
_vFilter
);
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(hr);
}
STDMETHODIMP
CLDAPDomain::Create(
THIS_ BSTR ClassName,
BSTR RelativeName,
IUnknown * FAR* ppObject
)
{
ULONG ObjectType = 0;
HRESULT hr;
POBJECTINFO pObjectInfo = NULL;
hr = GetObjectType(
gpFilters,
gdwMaxFilters,
ClassName,
(PDWORD)&ObjectType
);
BAIL_ON_FAILURE(hr);
hr = BuildObjectInfo(
_ADsPath,
RelativeName,
&pObjectInfo
);
BAIL_ON_FAILURE(hr);
hr = ValidateObject(
ObjectType,
pObjectInfo
);
if (SUCCEEDED(hr)) {
hr = HRESULT_FROM_WIN32(NERR_ResourceExists);
BAIL_ON_FAILURE(hr);
}
switch (ObjectType) {
case WINNT_USER_ID:
hr = CWinNTUser::CreateUser(
_ADsPath,
WINNT_DOMAIN_ID,
_Name,
NULL,
RelativeName,
ADS_OBJECT_UNBOUND,
IID_IUnknown,
(void **)ppObject
);
BAIL_ON_FAILURE(hr);
break;
case WINNT_GROUP_ID:
hr = CWinNTGroup::CreateGroup(
_ADsPath,
WINNT_DOMAIN_ID,
_Name,
NULL,
RelativeName,
WINNT_GROUP_GLOBAL,
ADS_OBJECT_UNBOUND,
IID_IUnknown,
(void **)ppObject
);
BAIL_ON_FAILURE(hr);
break;
case WINNT_COMPUTER_ID:
hr = E_NOTIMPL;
/*hr = CWinNTComputer::CreateComputer(
_ADsPath,
_Name,
RelativeName,
ADS_OBJECT_UNBOUND,
IID_IUnknown,
(void **)ppObject
);*/
BAIL_ON_FAILURE(hr);
break;
default:
RRETURN(E_ADS_UNKNOWN_OBJECT);
}
error:
RRETURN(hr);
}
STDMETHODIMP
CLDAPDomain::Delete(
BSTR bstrClassName,
BSTR bstrSourceName
)
{
ULONG ObjectType = 0;
POBJECTINFO pObjectInfo = NULL;
BOOL fStatus = FALSE;
HRESULT hr = S_OK;
WCHAR szUncServerName[MAX_PATH];
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);
BAIL_ON_FAILURE(hr);
break;
case WINNT_GROUP_ID:
hr = WinNTDeleteGroup(pObjectInfo);
BAIL_ON_FAILURE(hr);
break;
case WINNT_COMPUTER_ID:
hr = WinNTDeleteComputer(pObjectInfo);
BAIL_ON_FAILURE(hr);
break;
default:
hr = E_ADS_UNKNOWN_OBJECT;
BAIL_ON_FAILURE(hr);
}
RRETURN(hr);
error:
if (pObjectInfo) {
FreeObjectInfo(pObjectInfo);
}
RRETURN(hr);
}
#endif
/* IADsDomain methods */
STDMETHODIMP
CLDAPDomain::get_IsWorkgroup(THIS_ VARIANT_BOOL FAR* retval)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CLDAPDomain::get_MinPasswordLength(THIS_ long FAR* retval)
{
GET_PROPERTY_LONG((IADsDomain *)this, MinPasswordLength);
}
STDMETHODIMP
CLDAPDomain::put_MinPasswordLength(THIS_ long lMinPasswordLength)
{
PUT_PROPERTY_LONG((IADsDomain *)this, MinPasswordLength);
}
STDMETHODIMP
CLDAPDomain::get_MinPasswordAge(THIS_ long FAR* retval)
{
GET_PROPERTY_LONG((IADsDomain *)this, MinPasswordAge);
}
STDMETHODIMP CLDAPDomain::put_MinPasswordAge(THIS_ long lMinPasswordAge)
{
PUT_PROPERTY_LONG((IADsDomain *)this, MinPasswordAge);
}
STDMETHODIMP CLDAPDomain::get_MaxPasswordAge(THIS_ long FAR* retval)
{
GET_PROPERTY_LONG((IADsDomain *)this, MaxPasswordAge);
}
STDMETHODIMP CLDAPDomain::put_MaxPasswordAge(THIS_ long lMaxPasswordAge)
{
PUT_PROPERTY_LONG((IADsDomain *)this, MaxPasswordAge);
}
STDMETHODIMP CLDAPDomain::get_MaxBadPasswordsAllowed(THIS_ long FAR* retval)
{
GET_PROPERTY_LONG((IADsDomain *)this, MaxBadPasswordsAllowed);
}
STDMETHODIMP CLDAPDomain::put_MaxBadPasswordsAllowed(THIS_ long lMaxBadPasswordsAllowed)
{
PUT_PROPERTY_LONG((IADsDomain *)this, MaxBadPasswordsAllowed);
}
STDMETHODIMP CLDAPDomain::get_PasswordHistoryLength(THIS_ long FAR* retval)
{
GET_PROPERTY_LONG((IADsDomain *)this, PasswordHistoryLength);
}
STDMETHODIMP CLDAPDomain::put_PasswordHistoryLength(THIS_ long lPasswordHistoryLength)
{
PUT_PROPERTY_LONG((IADsDomain *)this, PasswordHistoryLength);
}
STDMETHODIMP CLDAPDomain::get_PasswordAttributes(THIS_ long FAR* retval)
{
GET_PROPERTY_LONG((IADsDomain *)this, PasswordAttributes);
}
STDMETHODIMP CLDAPDomain::put_PasswordAttributes(THIS_ long lPasswordAttributes)
{
PUT_PROPERTY_LONG((IADsDomain *)this, PasswordAttributes);
}
STDMETHODIMP CLDAPDomain::get_AutoUnlockInterval(THIS_ long FAR* retval)
{
GET_PROPERTY_LONG((IADsDomain *)this, AutoUnlockInterval);
}
STDMETHODIMP CLDAPDomain::put_AutoUnlockInterval(THIS_ long lAutoUnlockInterval)
{
PUT_PROPERTY_LONG((IADsDomain *)this, AutoUnlockInterval);
}
STDMETHODIMP CLDAPDomain::get_LockoutObservationInterval(THIS_ long FAR* retval)
{
GET_PROPERTY_LONG((IADsDomain *)this, LockoutObservationInterval);
}
STDMETHODIMP CLDAPDomain::put_LockoutObservationInterval(THIS_ long lLockoutObservationInterval)
{
PUT_PROPERTY_LONG((IADsDomain *)this, LockoutObservationInterval);
}
#if 0
STDMETHODIMP
CLDAPDomain::SetInfo(THIS)
{
HRESULT hr;
hr = SetInfo(0);
hr = SetInfo(2);
hr = SetInfo(3);
RRETURN(hr);
}
STDMETHODIMP
CLDAPDomain::GetInfo(THIS)
{
HRESULT hr;
hr = GetInfo(0, TRUE);
hr = GetInfo(2, TRUE);
hr = GetInfo(3, TRUE);
RRETURN(hr);
}
STDMETHODIMP
CLDAPDomain::GetInfo(
THIS_ DWORD dwApiLevel,
BOOL fExplicit
)
{
NET_API_STATUS nasStatus;
LPBYTE lpBuffer = NULL;
HRESULT hr;
WCHAR szPDCName[MAX_PATH];
hr = WinNTGetCachedPDCName(
_Name,
szPDCName
);
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(hr);
}
HRESULT
CLDAPDomain::UnMarshall(
LPBYTE lpBuffer,
DWORD dwApiLevel,
BOOL fExplicit
)
{
ADsAssert(lpBuffer);
switch (dwApiLevel) {
case 0:
RRETURN(UnMarshall_Level0(fExplicit, (LPUSER_MODALS_INFO_0)lpBuffer));
break;
case 2:
RRETURN(UnMarshall_Level2(fExplicit, (LPUSER_MODALS_INFO_2)lpBuffer));
break;
case 3:
RRETURN(UnMarshall_Level3(fExplicit, (LPUSER_MODALS_INFO_3)lpBuffer));
break;
default:
RRETURN(E_FAIL);
}
}
HRESULT
CLDAPDomain::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
);
RRETURN(S_OK);
}
HRESULT
CLDAPDomain::UnMarshall_Level2(
BOOL fExplicit,
LPUSER_MODALS_INFO_2 pUserInfo2
)
{
RRETURN(S_OK);
}
HRESULT
CLDAPDomain::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(S_OK);
}
STDMETHODIMP
CLDAPDomain::SetInfo(THIS_ DWORD dwApiLevel)
{
NET_API_STATUS nasStatus;
HRESULT hr;
LPBYTE lpBuffer = NULL;
DWORD dwParamErr = 0;
WCHAR szPDCName[MAX_PATH];
hr = WinNTGetCachedPDCName(
_Name,
szPDCName
);
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(hr);
}
HRESULT
CLDAPDomain::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
CLDAPDomain::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
CLDAPDomain::Marshall_Set_Level2(
LPWSTR szServerName,
LPUSER_MODALS_INFO_2 pUserInfo2
)
{
RRETURN(S_OK);
}
HRESULT
CLDAPDomain::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);
}
#endif