mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2232 lines
49 KiB
2232 lines
49 KiB
//---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1996
|
|
//
|
|
// File: cuser.cxx
|
|
//
|
|
// Contents: Host user object code
|
|
//
|
|
// History: Feb-14-96 t-ptam Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "NWCOMPAT.hxx"
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// Macro-ized implementation.
|
|
//
|
|
|
|
DEFINE_IDispatch_ExtMgr_Implementation(CNWCOMPATUser)
|
|
|
|
DEFINE_IADs_TempImplementation(CNWCOMPATUser)
|
|
|
|
DEFINE_IADs_PutGetImplementation(CNWCOMPATUser, UserClass, gdwUserTableSize)
|
|
|
|
DEFINE_IADsPropertyList_Implementation(CNWCOMPATUser, UserClass, gdwUserTableSize)
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::CNWCOMPATUser()
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CNWCOMPATUser::CNWCOMPATUser():
|
|
_pDispMgr(NULL),
|
|
_pExtMgr(NULL),
|
|
_pPropertyCache(NULL),
|
|
_ParentType(0),
|
|
_ServerName(NULL),
|
|
_szHostServerName(NULL)
|
|
{
|
|
ENLIST_TRACKING(CNWCOMPATUser);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::CreateUser
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::CreateUser(
|
|
BSTR Parent,
|
|
ULONG ParentType,
|
|
BSTR ServerName,
|
|
BSTR UserName,
|
|
DWORD dwObjectState,
|
|
REFIID riid,
|
|
void **ppvObj
|
|
)
|
|
{
|
|
CNWCOMPATUser FAR * pUser = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = AllocateUserObject(&pUser);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pUser->InitializeCoreObject(
|
|
Parent,
|
|
UserName,
|
|
USER_CLASS_NAME,
|
|
USER_SCHEMA_NAME,
|
|
CLSID_NWCOMPATUser,
|
|
dwObjectState
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = ADsAllocString( ServerName , &pUser->_ServerName);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = ADsAllocString( ServerName, &pUser->_szHostServerName);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pUser->QueryInterface(riid, ppvObj);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pUser->Release();
|
|
|
|
hr = pUser->_pExtMgr->FinalInitializeExtensions();
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
delete pUser;
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::~CNWCOMPATUser
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CNWCOMPATUser::~CNWCOMPATUser( )
|
|
{
|
|
ADsFreeString(_ServerName);
|
|
ADsFreeString(_szHostServerName);
|
|
|
|
delete _pExtMgr; // created last, destroyed first
|
|
|
|
delete _pDispMgr;
|
|
|
|
delete _pPropertyCache;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::QueryInterface
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CNWCOMPATUser::QueryInterface(
|
|
REFIID iid,
|
|
LPVOID FAR* ppv
|
|
)
|
|
{
|
|
if (ppv == NULL) {
|
|
RRETURN(E_POINTER);
|
|
}
|
|
|
|
if (IsEqualIID(iid, IID_IUnknown))
|
|
{
|
|
*ppv = (IADsUser FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IADsUser))
|
|
{
|
|
*ppv = (IADsUser FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IADs))
|
|
{
|
|
*ppv = (IADsUser FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IDispatch))
|
|
{
|
|
*ppv = (IADsUser FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_ISupportErrorInfo))
|
|
{
|
|
*ppv = (ISupportErrorInfo FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IADsPropertyList))
|
|
{
|
|
*ppv = (IADsPropertyList FAR *) this;
|
|
}
|
|
else if (_pExtMgr)
|
|
{
|
|
RRETURN(_pExtMgr->QueryInterface(iid,ppv));
|
|
}
|
|
else
|
|
{
|
|
*ppv = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
/* ISupportErrorInfo method */
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::InterfaceSupportsErrorInfo
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CNWCOMPATUser::InterfaceSupportsErrorInfo(
|
|
THIS_ REFIID riid
|
|
)
|
|
{
|
|
if (IsEqualIID(riid, IID_IADs) ||
|
|
IsEqualIID(riid, IID_IADsUser) ||
|
|
IsEqualIID(riid, IID_IADsPropertyList)) {
|
|
RRETURN(S_OK);
|
|
} else {
|
|
RRETURN(S_FALSE);
|
|
}
|
|
}
|
|
|
|
/* IADs methods */
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::SetInfo
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CNWCOMPATUser::SetInfo(THIS)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
POBJECTINFO pObjectInfo = NULL;
|
|
NW_USER_INFO NwUserInfo = {NULL, NULL, NULL, NULL};
|
|
|
|
//
|
|
// Bind an object to a real tangible resource if it is not bounded already.
|
|
//
|
|
|
|
if (GetObjectState() == ADS_OBJECT_UNBOUND) {
|
|
|
|
hr = BuildObjectInfo(
|
|
_Parent,
|
|
_Name,
|
|
&pObjectInfo
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = NWApiMakeUserInfo(
|
|
pObjectInfo->ComponentArray[0],
|
|
pObjectInfo->ComponentArray[1],
|
|
L"", // empty password initially
|
|
&NwUserInfo
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = NWApiCreateUser(
|
|
&NwUserInfo
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
SetObjectState(ADS_OBJECT_BOUND);
|
|
}
|
|
|
|
//
|
|
// Persist changes.
|
|
//
|
|
|
|
hr = SetInfo(USER_WILD_CARD_ID);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
error:
|
|
|
|
if (pObjectInfo) {
|
|
FreeObjectInfo(pObjectInfo);
|
|
}
|
|
|
|
(void) NWApiFreeUserInfo(&NwUserInfo) ;
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetInfo
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CNWCOMPATUser::GetInfo(THIS)
|
|
{
|
|
|
|
_pPropertyCache->flushpropcache();
|
|
|
|
RRETURN(GetInfo(
|
|
TRUE,
|
|
USER_WILD_CARD_ID
|
|
));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::AllocateUserObject
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::AllocateUserObject(
|
|
CNWCOMPATUser ** ppUser
|
|
)
|
|
{
|
|
CNWCOMPATUser FAR * pUser = NULL;
|
|
CAggregatorDispMgr FAR * pDispMgr = NULL;
|
|
CPropertyCache FAR * pPropertyCache = NULL;
|
|
CADsExtMgr FAR * pExtensionMgr = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Allocate memory for a User object.
|
|
//
|
|
|
|
pUser = new CNWCOMPATUser();
|
|
if (pUser == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// Create dispatch manager.
|
|
//
|
|
|
|
pDispMgr = new CAggregatorDispMgr;
|
|
if (pDispMgr == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// Load type info.
|
|
//
|
|
|
|
hr = LoadTypeInfoEntry(
|
|
pDispMgr,
|
|
LIBID_ADs,
|
|
IID_IADsUser,
|
|
(IADsUser *)pUser,
|
|
DISPID_REGULAR
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = LoadTypeInfoEntry(
|
|
pDispMgr,
|
|
LIBID_ADs,
|
|
IID_IADsPropertyList,
|
|
(IADsPropertyList *)pUser,
|
|
DISPID_VALUE
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = CPropertyCache::createpropertycache(
|
|
UserClass,
|
|
gdwUserTableSize,
|
|
(CCoreADsObject *)pUser,
|
|
&pPropertyCache
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pDispMgr->RegisterPropertyCache(
|
|
pPropertyCache
|
|
);
|
|
|
|
hr = ADSILoadExtensionManager(
|
|
USER_CLASS_NAME,
|
|
(IADs *) pUser,
|
|
pDispMgr,
|
|
&pExtensionMgr
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// Return.
|
|
//
|
|
pUser->_pPropertyCache = pPropertyCache;
|
|
pUser->_pDispMgr = pDispMgr;
|
|
pUser->_pExtMgr = pExtensionMgr;
|
|
|
|
*ppUser = pUser;
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
delete pDispMgr;
|
|
delete pPropertyCache;
|
|
delete pUser;
|
|
delete pExtensionMgr;
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::SetInfo
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CNWCOMPATUser::SetInfo(THIS_ DWORD dwPropertyID)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HRESULT hrTemp = S_OK;
|
|
NWCONN_HANDLE hConn = NULL;
|
|
|
|
//
|
|
// Get a handle to the bindery this object resides on.
|
|
//
|
|
|
|
hr = NWApiGetBinderyHandle(
|
|
&hConn,
|
|
_ServerName
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// Persist changes in cache.
|
|
//
|
|
|
|
hr = SetBusinessInfo(hConn);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = SetAccountRestrictions(hConn);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
error:
|
|
//
|
|
// Release handle.
|
|
//
|
|
|
|
if (hConn) {
|
|
hrTemp = NWApiReleaseBinderyHandle(hConn);
|
|
}
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::SetBusinessInfo
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::SetBusinessInfo(
|
|
NWCONN_HANDLE hConn
|
|
)
|
|
{
|
|
LPWSTR lpszRightSize = NULL;
|
|
LPWSTR pszFullName = NULL;
|
|
CHAR szData[(MAX_FULLNAME_LEN + 1)*2];
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Set FullName.
|
|
//
|
|
|
|
hr = GetLPTSTRPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("FullName"),
|
|
&pszFullName
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Cut the FullName down to no more than MAX_FULLNAME_LEN of characters.
|
|
//
|
|
|
|
lpszRightSize = (LPWSTR) AllocADsMem(
|
|
sizeof(WCHAR) * (MAX_FULLNAME_LEN + 1)
|
|
);
|
|
if (!lpszRightSize) {
|
|
RRETURN_EXP_IF_ERR(E_OUTOFMEMORY);
|
|
}
|
|
|
|
lpszRightSize[MAX_FULLNAME_LEN] = 0;
|
|
|
|
wcsncpy(
|
|
lpszRightSize,
|
|
pszFullName,
|
|
MAX_FULLNAME_LEN
|
|
);
|
|
|
|
//
|
|
// Convert bstr in ANSI string.
|
|
//
|
|
|
|
UnicodeToAnsiString(
|
|
lpszRightSize,
|
|
szData,
|
|
0
|
|
);
|
|
|
|
//
|
|
// Commit change.
|
|
//
|
|
|
|
hr = NWApiWriteProperty(
|
|
hConn,
|
|
_Name,
|
|
OT_USER,
|
|
NW_PROP_IDENTIFICATION,
|
|
(LPBYTE) szData
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
FreeADsMem(lpszRightSize);
|
|
}
|
|
|
|
error:
|
|
|
|
if (pszFullName) {
|
|
FreeADsStr(pszFullName);
|
|
}
|
|
|
|
RRETURN(S_OK);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::SetAccountRestrictions
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::SetAccountRestrictions(
|
|
NWCONN_HANDLE hConn
|
|
)
|
|
{
|
|
BOOL fModified = FALSE;
|
|
DATE daDate = 0;
|
|
DWORD dwNumSegment;
|
|
HRESULT hr = S_OK;
|
|
LC_STRUCTURE LoginCtrl;
|
|
LONG lData = 0;
|
|
LP_RPLY_SGMT_LST lpReplySegment = NULL;
|
|
LP_RPLY_SGMT_LST lpTemp = NULL;
|
|
SYSTEMTIME SysTime;
|
|
USER_DEFAULT UserDefault;
|
|
BOOL fBool;
|
|
WORD wDay = 0;
|
|
WORD wMonth = 0;
|
|
WORD wYear = 0;
|
|
WCHAR szTemp[MAX_PATH];
|
|
BYTE byDateTime[6];
|
|
BOOL fAccntLckModified;
|
|
|
|
hr = NWApiGetLOGIN_CONTROL(
|
|
hConn,
|
|
_Name,
|
|
&LoginCtrl
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// SET AccountDisabled.
|
|
//
|
|
|
|
hr = GetBOOLPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("AccountDisabled"),
|
|
&fBool
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
LoginCtrl.byAccountDisabled = (BYTE) fBool;
|
|
|
|
fModified = TRUE;
|
|
}
|
|
|
|
//
|
|
// SET AccountExpirationDate.
|
|
//
|
|
|
|
memset(byDateTime, 0, 6);
|
|
hr = GetNw312DATEPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("AccountExpirationDate"),
|
|
byDateTime
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
LoginCtrl.byAccountExpires[0] = (BYTE) byDateTime[0];
|
|
LoginCtrl.byAccountExpires[1] = (BYTE) byDateTime[1];
|
|
LoginCtrl.byAccountExpires[2] = (BYTE) byDateTime[2];
|
|
|
|
fModified = TRUE;
|
|
}
|
|
|
|
//
|
|
// SET AccountCanExpire.
|
|
//
|
|
|
|
hr = GetBOOLPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("AccountCanExpire"),
|
|
&fBool
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
if (fBool == FALSE) {
|
|
|
|
LoginCtrl.byAccountExpires[0] = 0;
|
|
LoginCtrl.byAccountExpires[1] = 0;
|
|
LoginCtrl.byAccountExpires[2] = 0;
|
|
|
|
fModified = TRUE;
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// SET GraceLoginsAllowed.
|
|
//
|
|
|
|
hr = GetDWORDPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("GraceLoginsAllowed"),
|
|
(PDWORD)&lData
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
LoginCtrl.byGraceLoginReset = (BYTE) lData;
|
|
|
|
fModified = TRUE;
|
|
}
|
|
|
|
//
|
|
// SET GraceLoginsRemaining.
|
|
//
|
|
|
|
hr = GetDWORDPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("GraceLoginsRemaining"),
|
|
(PDWORD)&lData
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
LoginCtrl.byGraceLogins = (BYTE) lData;
|
|
|
|
fModified = TRUE;
|
|
}
|
|
|
|
//
|
|
// SET IsAccountLocked.
|
|
//
|
|
|
|
//
|
|
// if this property not modified in cache, no need to set on svr
|
|
//
|
|
hr = _pPropertyCache->propertyismodified(
|
|
TEXT("IsAccountLocked"),
|
|
&fAccntLckModified
|
|
);
|
|
|
|
if ( SUCCEEDED(hr) && fAccntLckModified==TRUE ) {
|
|
|
|
hr = GetBOOLPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("IsAccountLocked"),
|
|
&fBool
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// If fBool is changed from TRUE to FALSE, set wBadLogins
|
|
// back to 0 -> this will unlock account on nw svr
|
|
//
|
|
|
|
if (fBool == FALSE) {
|
|
|
|
LoginCtrl.wBadLogins = 0;
|
|
fModified = TRUE;
|
|
|
|
}else {
|
|
|
|
//
|
|
// Reset it to FALSE if it is changed to TRUE.
|
|
// -> cannot lock an account on nwsvr thru' adsi
|
|
//
|
|
|
|
fBool = FALSE;
|
|
|
|
hr = SetBOOLPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("IsAccountLocked"),
|
|
fBool,
|
|
TRUE
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// SET IsAdmin.
|
|
//
|
|
|
|
hr = GetBOOLPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("IsAdmin"),
|
|
&fBool
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
hr = NWApiUserAsSupervisor(
|
|
hConn,
|
|
_Name,
|
|
fBool
|
|
);
|
|
|
|
//
|
|
// For beta, disabling the bail. It does not work in the user not
|
|
// supervisor mode.
|
|
//
|
|
|
|
// BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
//
|
|
// SET MaxLogins.
|
|
//
|
|
|
|
hr = GetDWORDPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("MaxLogins"),
|
|
(PDWORD)&lData
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
LoginCtrl.wMaxConnections = NWApiReverseWORD(
|
|
(WORD) lData
|
|
);
|
|
|
|
fModified = TRUE;
|
|
}
|
|
|
|
//
|
|
// SET PasswordExpirationDate.
|
|
//
|
|
|
|
memset(byDateTime, 0, 6);
|
|
hr = GetNw312DATEPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("PasswordExpirationDate"),
|
|
byDateTime
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
|
|
LoginCtrl.byPasswordExpires[0] = (BYTE) byDateTime[0];
|
|
LoginCtrl.byPasswordExpires[1] = (BYTE) byDateTime[1];
|
|
LoginCtrl.byPasswordExpires[2] = (BYTE) byDateTime[2];
|
|
|
|
fModified = TRUE;
|
|
}
|
|
|
|
//
|
|
// SET PasswordCanExpire.
|
|
//
|
|
|
|
hr = GetBOOLPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("PasswordCanExpire"),
|
|
&fBool
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
if (fBool == FALSE) {
|
|
|
|
//
|
|
// If passowrd cannot expire, set password expiration date to zero.
|
|
// This is what SysCon does.
|
|
//
|
|
|
|
LoginCtrl.byPasswordExpires[0] = 0;
|
|
LoginCtrl.byPasswordExpires[1] = 0;
|
|
LoginCtrl.byPasswordExpires[2] = 0;
|
|
|
|
fModified = TRUE;
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// SET PasswordMinimumLength.
|
|
//
|
|
|
|
hr = GetDWORDPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("PasswordMinimumLength"),
|
|
(PDWORD)&lData
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
LoginCtrl.byMinPasswordLength = (BYTE) lData;
|
|
|
|
fModified = TRUE;
|
|
}
|
|
|
|
//
|
|
// SET PasswordRequired. The section below must goes before "Set
|
|
// PasswordMinimumLength" for it to make sense.
|
|
//
|
|
|
|
hr = GetBOOLPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("PasswordRequired"),
|
|
&fBool
|
|
);
|
|
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// If Password is required, set PasswordMinimumLength to default value.
|
|
//
|
|
|
|
//
|
|
// If Password is not required, set PasswordMinimumLength to 0. Again,
|
|
// this is what SysCon does.
|
|
//
|
|
|
|
if (fBool) {
|
|
if (!LoginCtrl.byMinPasswordLength) {
|
|
LoginCtrl.byMinPasswordLength = DEFAULT_MIN_PSWD_LEN;
|
|
}
|
|
}else{
|
|
LoginCtrl.byMinPasswordLength = 0;
|
|
}
|
|
|
|
fModified = TRUE;
|
|
}
|
|
|
|
//
|
|
// Set LoginHours
|
|
//
|
|
OctetString octString;
|
|
|
|
hr = GetOctetPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("LoginHours"),
|
|
&octString
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
memcpy(LoginCtrl.byLoginTimes, octString.pByte, octString.dwSize);
|
|
FreeADsMem(octString.pByte);
|
|
fModified = TRUE;
|
|
}
|
|
|
|
//
|
|
// Set RequireUniquePassword.
|
|
//
|
|
|
|
hr = GetBOOLPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("RequireUniquePassword"),
|
|
&fBool
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
LoginCtrl.byRestrictions = fBool ? REQUIRE_UNIQUE_PSWD : 0;
|
|
|
|
fModified = TRUE;
|
|
|
|
}
|
|
|
|
//
|
|
// Commit changes of the properties associated with LOGIN_CONTROL.
|
|
//
|
|
|
|
if (fModified == TRUE) {
|
|
|
|
hr = NWApiWriteProperty(
|
|
hConn,
|
|
_Name,
|
|
OT_USER,
|
|
NW_PROP_LOGIN_CONTROL,
|
|
(LPBYTE) &LoginCtrl
|
|
);
|
|
}
|
|
else {
|
|
|
|
hr = S_OK;
|
|
}
|
|
|
|
error:
|
|
|
|
if (lpReplySegment) {
|
|
DELETE_LIST(lpReplySegment);
|
|
}
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetInfo
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CNWCOMPATUser::GetInfo(
|
|
BOOL fExplicit,
|
|
DWORD dwPropertyID
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HRESULT hrTemp = S_OK;
|
|
NWCONN_HANDLE hConn = NULL;
|
|
|
|
if (GetObjectState() == ADS_OBJECT_UNBOUND) {
|
|
RRETURN_EXP_IF_ERR(E_ADS_OBJECT_UNBOUND);
|
|
}
|
|
|
|
//
|
|
// Get a handle to the bindery this object resides on.
|
|
//
|
|
|
|
hr = NWApiGetBinderyHandle(
|
|
&hConn,
|
|
_ServerName
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// Fill in all property caches with values - explicit, or return the
|
|
// indicated property - implicit.
|
|
//
|
|
|
|
if (fExplicit) {
|
|
hr = ExplicitGetInfo(hConn, fExplicit);
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
else {
|
|
hr = ImplicitGetInfo(hConn, dwPropertyID, fExplicit);
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
error:
|
|
//
|
|
// Release handle.
|
|
//
|
|
|
|
if (hConn) {
|
|
hrTemp = NWApiReleaseBinderyHandle(hConn);
|
|
}
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::ExplicitGetInfo
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::ExplicitGetInfo(
|
|
NWCONN_HANDLE hConn,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LC_STRUCTURE LoginCtrlStruct;
|
|
|
|
//
|
|
// Get BusinessInfo functional set.
|
|
//
|
|
|
|
hr = GetProperty_FullName(
|
|
hConn,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// Get LOGIN_CONTROL, which is used in AccountRestriction functional set &
|
|
// AccountStatistics functional set.
|
|
//
|
|
|
|
hr = NWApiGetLOGIN_CONTROL(
|
|
hConn,
|
|
_Name,
|
|
&LoginCtrlStruct
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
//
|
|
// Get AccountRestriction functional set.
|
|
//
|
|
|
|
hr = GetProperty_LoginHours(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = GetProperty_AccountDisabled(
|
|
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = GetProperty_AccountExpirationDate(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = GetProperty_CanAccountExpire(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = GetProperty_GraceLoginsAllowed(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = GetProperty_GraceLoginsRemaining(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = GetProperty_IsAccountLocked(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = GetProperty_IsAdmin(
|
|
hConn,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = GetProperty_MaxLogins(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = GetProperty_CanPasswordExpire(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = GetProperty_PasswordExpirationDate(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = GetProperty_PasswordMinimumLength(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = GetProperty_PasswordRequired(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = GetProperty_RequireUniquePassword(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// Get AccountStatistics functional set.
|
|
//
|
|
|
|
hr = GetProperty_BadLoginAddress(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = GetProperty_LastLogin(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
//
|
|
// if NWApiGetLOGIN_CONTROL failed, it's okay, we just ignore
|
|
// it and don't load those properties into the cache
|
|
//
|
|
hr = S_OK;
|
|
|
|
error:
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::ImplicitGetInfo
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::ImplicitGetInfo(
|
|
NWCONN_HANDLE hConn,
|
|
DWORD dwPropertyID,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (dwPropertyID < 100) {
|
|
hr = GetBusinessInfo(
|
|
hConn,
|
|
dwPropertyID,
|
|
fExplicit
|
|
);
|
|
}
|
|
else if (dwPropertyID < 200) {
|
|
hr = GetAccountRestrictions(
|
|
hConn,
|
|
dwPropertyID,
|
|
fExplicit
|
|
);
|
|
}
|
|
else if (dwPropertyID < 300) {
|
|
hr = GetAccountStatistics(
|
|
hConn,
|
|
dwPropertyID,
|
|
fExplicit
|
|
);
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetBusinessInfo
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetBusinessInfo(
|
|
NWCONN_HANDLE hConn,
|
|
DWORD dwPropertyID,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
switch (dwPropertyID) {
|
|
|
|
case USER_FULLNAME_ID:
|
|
hr = GetProperty_FullName(
|
|
hConn,
|
|
fExplicit
|
|
);
|
|
break;
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetAccountRestrictions
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetAccountRestrictions(
|
|
NWCONN_HANDLE hConn,
|
|
DWORD dwPropertyID,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LC_STRUCTURE LoginCtrlStruct;
|
|
|
|
//
|
|
// Get LOGIN_CONTROL.
|
|
//
|
|
|
|
hr = NWApiGetLOGIN_CONTROL(
|
|
hConn,
|
|
_Name,
|
|
&LoginCtrlStruct
|
|
);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Get property.
|
|
//
|
|
|
|
switch (dwPropertyID) {
|
|
|
|
case USER_ACCOUNTDISABLED_ID:
|
|
hr = GetProperty_AccountDisabled(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
break;
|
|
|
|
case USER_ACCOUNTEXPIRATIONDATE_ID:
|
|
hr = GetProperty_AccountExpirationDate(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
break;
|
|
|
|
case USER_CANACCOUNTEXPIRE_ID:
|
|
hr = GetProperty_CanAccountExpire(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
break;
|
|
|
|
case USER_GRACELOGINSALLOWED_ID:
|
|
hr = GetProperty_GraceLoginsAllowed(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
break;
|
|
|
|
case USER_GRACELOGINSREMAINING_ID:
|
|
hr = GetProperty_GraceLoginsRemaining(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
break;
|
|
|
|
case USER_ISACCOUNTLOCKED_ID:
|
|
hr = GetProperty_IsAccountLocked(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
break;
|
|
|
|
case USER_ISADMIN_ID:
|
|
hr = GetProperty_IsAdmin(
|
|
hConn,
|
|
fExplicit
|
|
);
|
|
break;
|
|
|
|
case USER_MAXLOGINS_ID:
|
|
hr = GetProperty_MaxLogins(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
break;
|
|
|
|
case USER_CANPASSWORDEXPIRE_ID:
|
|
hr = GetProperty_CanPasswordExpire(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
break;
|
|
|
|
case USER_PASSWORDEXPIRATIONDATE_ID:
|
|
hr = GetProperty_PasswordExpirationDate(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
break;
|
|
|
|
case USER_PASSWORDMINIMUMLENGTH_ID:
|
|
hr = GetProperty_PasswordMinimumLength(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
break;
|
|
|
|
case USER_PASSWORDREQUIRED_ID:
|
|
hr = GetProperty_PasswordRequired(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
break;
|
|
|
|
case USER_REQUIREUNIQUEPASSWORD_ID:
|
|
hr = GetProperty_RequireUniquePassword(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
break;
|
|
|
|
case USER_LOGINHOURS_ID:
|
|
hr = GetProperty_LoginHours(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
break;
|
|
|
|
}
|
|
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
//
|
|
// if NWApiGetLOGIN_CONTROL failed, it's okay, we just ignore
|
|
// it and don't load those properties into the cache
|
|
//
|
|
hr = S_OK;
|
|
|
|
error:
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetAccountStatistics
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetAccountStatistics(
|
|
NWCONN_HANDLE hConn,
|
|
DWORD dwPropertyID,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LC_STRUCTURE LoginCtrlStruct;
|
|
|
|
//
|
|
// Get LOGIN_CONTROL.
|
|
//
|
|
|
|
hr = NWApiGetLOGIN_CONTROL(
|
|
hConn,
|
|
_Name,
|
|
&LoginCtrlStruct
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Get property.
|
|
//
|
|
|
|
switch (dwPropertyID) {
|
|
|
|
case USER_BADLOGINADDRESS_ID:
|
|
hr = GetProperty_BadLoginAddress(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
break;
|
|
|
|
case USER_LASTLOGIN_ID:
|
|
hr = GetProperty_LastLogin(
|
|
hConn,
|
|
LoginCtrlStruct,
|
|
fExplicit
|
|
);
|
|
break;
|
|
}
|
|
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
//
|
|
// if NWApiGetLOGIN_CONTROL failed, it's okay, we just ignore
|
|
// it and don't load those properties into the cache
|
|
//
|
|
hr = S_OK;
|
|
|
|
error:
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetProperty_FullName
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetProperty_FullName(
|
|
NWCONN_HANDLE hConn,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
LPWSTR lpszFullName = NULL;
|
|
CHAR szFullName[MAX_FULLNAME_LEN + 1];
|
|
DWORD dwNumSegment = 0;
|
|
HRESULT hr = S_OK;
|
|
LP_RPLY_SGMT_LST lpReplySegment = NULL;
|
|
LP_RPLY_SGMT_LST lpTemp = NULL; // Used by DELETE_LIST macro below
|
|
|
|
//
|
|
// Get IDENTIFICATIOIN. This property contains the full name of an object.
|
|
//
|
|
|
|
hr = NWApiGetProperty(
|
|
_Name,
|
|
NW_PROP_IDENTIFICATION,
|
|
OT_USER,
|
|
hConn,
|
|
&lpReplySegment,
|
|
&dwNumSegment
|
|
);
|
|
|
|
//
|
|
// This call will fail for those users who has never set
|
|
// their Fullname, ie. "IDENTIFICATION" is not created. Per Raid #34833
|
|
// (resolved By Design), there is no way to distinguish a failure for
|
|
// the property not existing from a general failure --- they both return the
|
|
// same error code. In general, it is expected that a Bindery user will have
|
|
// the IDENTIFICATION property, so if this call fails we assume it was because
|
|
// the property didn't exist. In this case, we return success, since it was
|
|
// successful, there just didn't happen to be an IDENTIFICATION.
|
|
//
|
|
if (FAILED(hr)) {
|
|
hr = S_OK;
|
|
goto error;
|
|
}
|
|
|
|
//
|
|
// Convert result into a UNICODE string.
|
|
//
|
|
|
|
strcpy(szFullName, lpReplySegment->Segment);
|
|
|
|
lpszFullName = (LPWSTR) AllocADsMem(
|
|
(strlen(szFullName)+1) * sizeof(WCHAR)
|
|
);
|
|
if (!lpszFullName)
|
|
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
|
|
|
|
AnsiToUnicodeString(
|
|
szFullName,
|
|
lpszFullName,
|
|
0
|
|
);
|
|
|
|
//
|
|
// Unmarshall.
|
|
//
|
|
|
|
hr = SetLPTSTRPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("FullName"),
|
|
(LPWSTR)lpszFullName,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
error:
|
|
|
|
if (lpszFullName) {
|
|
|
|
FreeADsMem(lpszFullName);
|
|
}
|
|
if (lpReplySegment) {
|
|
DELETE_LIST(lpReplySegment);
|
|
}
|
|
|
|
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetProperty_AccountDisabled
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetProperty_AccountDisabled(
|
|
NWCONN_HANDLE hConn,
|
|
LC_STRUCTURE LoginCtrlStruct,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
BOOL dwBool = TRUE;
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Put value into a variant.
|
|
//
|
|
|
|
dwBool = (BOOL) LoginCtrlStruct.byAccountDisabled;
|
|
|
|
//
|
|
// Unmarshall.
|
|
//
|
|
|
|
hr = SetBOOLPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("AccountDisabled"),
|
|
dwBool,
|
|
fExplicit
|
|
);
|
|
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetProperty_AccountExpirationDate
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetProperty_AccountExpirationDate(
|
|
NWCONN_HANDLE hConn,
|
|
LC_STRUCTURE LoginCtrlStruct,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BYTE byDateTime[6];
|
|
BYTE byNoDateTime[6];
|
|
|
|
memset(byNoDateTime, 0, 6);
|
|
memset(byDateTime, 0, 6);
|
|
memcpy(byDateTime, LoginCtrlStruct.byAccountExpires, 3);
|
|
|
|
//
|
|
// LoginCtrlSturct.byAccountExpires == 000 indicates no expired date
|
|
//
|
|
if (memcmp(byDateTime, byNoDateTime, 3)!=0) {
|
|
|
|
hr = SetNw312DATEPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("AccountExpirationDate"),
|
|
byDateTime,
|
|
fExplicit
|
|
);
|
|
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
error:
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetProperty_CanAccountExpire
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetProperty_CanAccountExpire(
|
|
NWCONN_HANDLE hConn,
|
|
LC_STRUCTURE LoginCtrlStruct,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
BOOL dwBool = TRUE;
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Account cannot expire if there is no expiration date.
|
|
//
|
|
|
|
if ((LoginCtrlStruct.byAccountExpires[0] == 0) &&
|
|
(LoginCtrlStruct.byAccountExpires[1] == 0) &&
|
|
(LoginCtrlStruct.byAccountExpires[2] == 0)) {
|
|
|
|
dwBool = FALSE;
|
|
}
|
|
|
|
//
|
|
// Unmarshall.
|
|
//
|
|
|
|
hr = SetBOOLPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("AccountCanExpire"),
|
|
dwBool,
|
|
fExplicit
|
|
);
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetProperty_GraceLoginsAllowed
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetProperty_GraceLoginsAllowed(
|
|
NWCONN_HANDLE hConn,
|
|
LC_STRUCTURE LoginCtrlStruct,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LONG lGraceLoginsAllowed = 0;
|
|
|
|
//
|
|
// Get "byGraceLoginReset". The property is not meaningful when it equals
|
|
// to 0xff.
|
|
//
|
|
|
|
if (LoginCtrlStruct.byGraceLoginReset != 0xff) {
|
|
|
|
lGraceLoginsAllowed = (LONG) LoginCtrlStruct.byGraceLoginReset;
|
|
}
|
|
|
|
//
|
|
// Unmarshall.
|
|
//
|
|
|
|
hr = SetDWORDPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("GraceLoginsAllowed"),
|
|
(DWORD)lGraceLoginsAllowed,
|
|
fExplicit
|
|
);
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetProperty_GraceLoginsRemaining
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetProperty_GraceLoginsRemaining(
|
|
NWCONN_HANDLE hConn,
|
|
LC_STRUCTURE LoginCtrlStruct,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LONG lGraceLoginsRemaining = 0;
|
|
|
|
//
|
|
// Get "byGraceLogins". The property is not meaningful when it equals to
|
|
// 0xff.
|
|
//
|
|
|
|
if (LoginCtrlStruct.byGraceLogins != 0xff) {
|
|
|
|
lGraceLoginsRemaining = (LONG) LoginCtrlStruct.byGraceLogins;
|
|
}
|
|
|
|
//
|
|
// Unmarshall.
|
|
//
|
|
|
|
hr = SetDWORDPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("GraceLoginsRemaining"),
|
|
(DWORD)lGraceLoginsRemaining,
|
|
fExplicit
|
|
);
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetProperty_IsAccountLocked
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetProperty_IsAccountLocked(
|
|
NWCONN_HANDLE hConn,
|
|
LC_STRUCTURE LoginCtrlStruct,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
BOOL dwBool = FALSE;
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Account is locked when wBadLogins = 0xffff.
|
|
//
|
|
|
|
if (LoginCtrlStruct.wBadLogins == 0xffff) {
|
|
|
|
dwBool = TRUE;
|
|
}
|
|
|
|
//
|
|
// Unmarshall.
|
|
//
|
|
|
|
hr = SetBOOLPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("IsAccountLocked"),
|
|
dwBool,
|
|
fExplicit
|
|
);
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetProperty_IsAdmin
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetProperty_IsAdmin(
|
|
NWCONN_HANDLE hConn,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
BOOL dwBool = TRUE;
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Check if this user has the same security as the supervisor. If it does,
|
|
// then it is an admin.
|
|
//
|
|
|
|
hr = NWApiIsObjectInSet(
|
|
hConn,
|
|
_Name,
|
|
OT_USER,
|
|
NW_PROP_SECURITY_EQUALS,
|
|
NW_PROP_SUPERVISOR,
|
|
OT_USER
|
|
);
|
|
|
|
// Per bug #33322 (resolved By Design), there is no way to distinguish
|
|
// "no such object" from a general failure. So we assume that any failure
|
|
// is "no such object".
|
|
|
|
if (FAILED(hr)) {
|
|
dwBool = FALSE;
|
|
hr = S_OK;
|
|
}
|
|
|
|
//
|
|
// Unmarshall.
|
|
//
|
|
|
|
hr = SetBOOLPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("IsAdmin"),
|
|
dwBool,
|
|
fExplicit
|
|
);
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetProperty_MaxLogins
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetProperty_MaxLogins(
|
|
NWCONN_HANDLE hConn,
|
|
LC_STRUCTURE LoginCtrlStruct,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LONG lMaxLogins = 0;
|
|
|
|
//
|
|
// Get "wMaxConnections".
|
|
//
|
|
|
|
lMaxLogins = (LONG) NWApiReverseWORD(
|
|
LoginCtrlStruct.wMaxConnections
|
|
);
|
|
|
|
//
|
|
// Unmarshall.
|
|
//
|
|
|
|
hr = SetDWORDPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("MaxLogins"),
|
|
(DWORD)lMaxLogins,
|
|
fExplicit
|
|
);
|
|
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetProperty_CanPasswordExpire
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetProperty_CanPasswordExpire(
|
|
NWCONN_HANDLE hConn,
|
|
LC_STRUCTURE LoginCtrlStruct,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
BOOL dwBool = TRUE;
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Password cannot expire if there is no expiration date.
|
|
//
|
|
|
|
if ((LoginCtrlStruct.byPasswordExpires[0] == 0) &&
|
|
(LoginCtrlStruct.byPasswordExpires[1] == 0) &&
|
|
(LoginCtrlStruct.byPasswordExpires[2] == 0)) {
|
|
|
|
dwBool = FALSE;
|
|
}
|
|
|
|
//
|
|
// Unmarshall.
|
|
//
|
|
hr = SetBOOLPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("PasswordCanExpire"),
|
|
dwBool,
|
|
fExplicit
|
|
);
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetProperty_PasswordExpirationDate
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetProperty_PasswordExpirationDate(
|
|
NWCONN_HANDLE hConn,
|
|
LC_STRUCTURE LoginCtrlStruct,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BYTE byDateTime[6];
|
|
|
|
memset(byDateTime, 0, 6);
|
|
memcpy(byDateTime, LoginCtrlStruct.byPasswordExpires, 3);
|
|
|
|
hr = SetNw312DATEPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("PasswordExpirationDate"),
|
|
byDateTime,
|
|
fExplicit
|
|
);
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetProperty_PasswordMinimumLength
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetProperty_PasswordMinimumLength(
|
|
NWCONN_HANDLE hConn,
|
|
LC_STRUCTURE LoginCtrlStruct,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LONG lMinimumLength = 0;
|
|
|
|
//
|
|
// Get "byMinPasswordLength".
|
|
//
|
|
|
|
lMinimumLength = (LONG) LoginCtrlStruct.byMinPasswordLength;
|
|
|
|
//
|
|
// Unmarshall.
|
|
//
|
|
|
|
hr = SetDWORDPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("PasswordMinimumLength"),
|
|
(DWORD)lMinimumLength,
|
|
fExplicit
|
|
);
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetProperty_PasswordRequired
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetProperty_PasswordRequired(
|
|
NWCONN_HANDLE hConn,
|
|
LC_STRUCTURE LoginCtrlStruct,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
BOOL dwBool = TRUE;
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Password is not required if "byMinPasswordLength" is 0.
|
|
//
|
|
|
|
if (LoginCtrlStruct.byMinPasswordLength == 0) {
|
|
|
|
dwBool = FALSE;
|
|
}
|
|
|
|
//
|
|
// Unmarshall.
|
|
//
|
|
|
|
hr = SetBOOLPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("PasswordRequired"),
|
|
dwBool,
|
|
fExplicit
|
|
);
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetProperty_RequireUniquePassword
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetProperty_RequireUniquePassword(
|
|
NWCONN_HANDLE hConn,
|
|
LC_STRUCTURE LoginCtrlStruct,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
BOOL dwBool = TRUE;
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// If byRestrictions = 0, "RequireUniquePassword" = FALSE.
|
|
//
|
|
|
|
if (LoginCtrlStruct.byRestrictions == 0) {
|
|
|
|
dwBool = FALSE;
|
|
}
|
|
|
|
//
|
|
// Unmarshall.
|
|
//
|
|
hr = SetBOOLPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("RequireUniquePassword"),
|
|
dwBool,
|
|
fExplicit
|
|
);
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
HRESULT
|
|
CNWCOMPATUser::GetProperty_LoginHours(
|
|
NWCONN_HANDLE hConn,
|
|
LC_STRUCTURE LoginCtrlStruct,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
BOOL dwBool = TRUE;
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Unmarshall.
|
|
//
|
|
hr = SetOctetPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("LoginHours"),
|
|
(BYTE*)LoginCtrlStruct.byLoginTimes,
|
|
24,
|
|
fExplicit
|
|
);
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetProperty_BadLoginAddress
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetProperty_BadLoginAddress(
|
|
NWCONN_HANDLE hConn,
|
|
LC_STRUCTURE LoginCtrlStruct,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPWSTR lpszTemp = NULL;
|
|
|
|
//
|
|
// Put address together in the format described in spec.
|
|
//
|
|
|
|
lpszTemp = (LPWSTR) AllocADsMem((NET_ADDRESS_NUM_CHAR+1)*sizeof(WCHAR));
|
|
if (!lpszTemp) {
|
|
RRETURN(E_OUTOFMEMORY);
|
|
}
|
|
|
|
wsprintf(
|
|
lpszTemp,
|
|
L"%s:%02X%02X%02X%02X.%02X%02X%02X%02X%02X%02X.%02X%02X",
|
|
bstrAddressTypeString,
|
|
LoginCtrlStruct.byBadLoginAddr[10],
|
|
LoginCtrlStruct.byBadLoginAddr[11],
|
|
LoginCtrlStruct.byBadLoginAddr[0],
|
|
LoginCtrlStruct.byBadLoginAddr[1],
|
|
LoginCtrlStruct.byBadLoginAddr[2],
|
|
LoginCtrlStruct.byBadLoginAddr[3],
|
|
LoginCtrlStruct.byBadLoginAddr[4],
|
|
LoginCtrlStruct.byBadLoginAddr[5],
|
|
LoginCtrlStruct.byBadLoginAddr[6],
|
|
LoginCtrlStruct.byBadLoginAddr[7],
|
|
LoginCtrlStruct.byBadLoginAddr[8],
|
|
LoginCtrlStruct.byBadLoginAddr[9]
|
|
);
|
|
|
|
//
|
|
// Unmarshall.
|
|
//
|
|
|
|
hr = SetLPTSTRPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("BadLoginAddress"),
|
|
(LPWSTR)lpszTemp,
|
|
fExplicit
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
error:
|
|
|
|
if (lpszTemp) {
|
|
|
|
FreeADsMem(lpszTemp);
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Function: CNWCOMPATUser::GetProperty_LastLogin
|
|
//
|
|
// Synopsis:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CNWCOMPATUser::GetProperty_LastLogin(
|
|
NWCONN_HANDLE hConn,
|
|
LC_STRUCTURE LoginCtrlStruct,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
BYTE byNoDateTime[6];
|
|
|
|
memset(byNoDateTime, 0, 6);
|
|
|
|
//
|
|
// LastLogin==000000 indicates no or unknown LastLogin
|
|
//
|
|
if (memcmp(LoginCtrlStruct.byLastLogin, byNoDateTime, 6) != 0) {
|
|
|
|
hr = SetNw312DATEPropertyInCache(
|
|
_pPropertyCache,
|
|
TEXT("LastLogin"),
|
|
LoginCtrlStruct.byLastLogin,
|
|
fExplicit
|
|
);
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
ConvertNW312DateToVariant(
|
|
BYTE byDateTime[],
|
|
PDATE pDate
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
WORD wYear;
|
|
|
|
//
|
|
// Subtract 80 from wYear for NWApiMakeVariantTime.
|
|
//
|
|
|
|
wYear = (WORD)byDateTime[0];
|
|
|
|
if (wYear != 0) {
|
|
wYear -= 80;
|
|
}
|
|
|
|
//
|
|
// Convert into Variant Time.
|
|
//
|
|
|
|
hr = NWApiMakeVariantTime(
|
|
pDate,
|
|
(WORD)byDateTime[2],
|
|
(WORD)byDateTime[1],
|
|
wYear,
|
|
0,0,0
|
|
);
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
ConvertVariantToNW312Date(
|
|
DATE daDate,
|
|
BYTE byDateTime[]
|
|
)
|
|
{
|
|
WORD wDay;
|
|
WORD wYear;
|
|
WORD wMonth;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = NWApiBreakVariantTime(
|
|
daDate,
|
|
&wDay,
|
|
&wMonth,
|
|
&wYear
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
byDateTime[0] = (BYTE)wYear;
|
|
byDateTime[1] = (BYTE)wMonth;
|
|
byDateTime[2] = (BYTE)wDay;
|
|
|
|
byDateTime[3] = 0;
|
|
byDateTime[4] = 0;
|
|
byDateTime[5] = 0;
|
|
|
|
error:
|
|
|
|
RRETURN(hr);
|
|
}
|