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