Source code of Windows XP (NT5)
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

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