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.
867 lines
19 KiB
867 lines
19 KiB
/* ----------------------------------------------------------------------
|
|
|
|
Module: ULS.DLL (Service Provider)
|
|
File: spluser.cpp
|
|
Content: This file contains the local user object.
|
|
History:
|
|
10/15/96 Chu, Lon-Chan [lonchanc]
|
|
Created.
|
|
|
|
Copyright (c) Microsoft Corporation 1996-1997
|
|
|
|
---------------------------------------------------------------------- */
|
|
|
|
#include "ulsp.h"
|
|
#include "spinc.h"
|
|
|
|
// Array of constant strings for user object's attribute names
|
|
//
|
|
const TCHAR *c_apszUserStdAttrNames[COUNT_ENUM_USERATTR] =
|
|
{
|
|
TEXT ("cn"),
|
|
TEXT ("givenname"),
|
|
TEXT ("surname"),
|
|
TEXT ("rfc822mailbox"),
|
|
TEXT ("location"),
|
|
#ifdef USE_DEFAULT_COUNTRY
|
|
TEXT ("aCountryName"),
|
|
#endif
|
|
TEXT ("comment"),
|
|
TEXT ("sipaddress"),
|
|
TEXT ("sflags"),
|
|
TEXT ("c"),
|
|
|
|
TEXT ("ssecurity"),
|
|
TEXT ("sttl"),
|
|
|
|
TEXT ("objectClass"),
|
|
TEXT ("o"),
|
|
};
|
|
|
|
|
|
/* ---------- public methods ----------- */
|
|
|
|
|
|
UlsLdap_CLocalUser::
|
|
UlsLdap_CLocalUser ( VOID )
|
|
{
|
|
// Reference count
|
|
//
|
|
m_cRefs = 0;
|
|
|
|
// User object's signature
|
|
//
|
|
m_uSignature = USEROBJ_SIGNATURE;
|
|
|
|
// Clean up attached server info structure
|
|
//
|
|
ZeroMemory (&m_ServerInfo, sizeof (m_ServerInfo));
|
|
|
|
// Clean up the scratch buffer for caching pointers to attribute values
|
|
//
|
|
ZeroMemory (&m_UserInfo, sizeof (m_UserInfo));
|
|
|
|
// Clean up DN (old and current ones)
|
|
m_pszDN = NULL;
|
|
m_pszOldDN = NULL;
|
|
|
|
// Clean up the refresh search filter
|
|
//
|
|
m_pszRefreshFilter = NULL;
|
|
|
|
// Indicate this user is not registered yet
|
|
//
|
|
SetRegNone ();
|
|
|
|
// Reset time to live value
|
|
m_uTTL = ULS_DEF_REFRESH_MINUTE; // in unit of minute: no effect on current ils, but to avoid legacy issue later
|
|
m_dwIPAddress = 0;
|
|
}
|
|
|
|
|
|
UlsLdap_CLocalUser::
|
|
~UlsLdap_CLocalUser ( VOID )
|
|
{
|
|
// Invalidate the user object's signature
|
|
//
|
|
m_uSignature = (ULONG) -1;
|
|
|
|
// Free server info structure
|
|
//
|
|
::IlsFreeServerInfo (&m_ServerInfo);
|
|
|
|
// Free DN (old and current ones)
|
|
//
|
|
MemFree (m_pszDN);
|
|
MemFree (m_pszOldDN);
|
|
|
|
// Free the refresh search filter
|
|
//
|
|
MemFree (m_pszRefreshFilter);
|
|
}
|
|
|
|
|
|
ULONG UlsLdap_CLocalUser::
|
|
AddRef ( VOID )
|
|
{
|
|
InterlockedIncrement (&m_cRefs);
|
|
return m_cRefs;
|
|
}
|
|
|
|
|
|
ULONG UlsLdap_CLocalUser::
|
|
Release ( VOID )
|
|
{
|
|
MyAssert (m_cRefs != 0);
|
|
|
|
if (m_cRefs != 0)
|
|
{
|
|
InterlockedDecrement (&m_cRefs);
|
|
}
|
|
|
|
ULONG cRefs = m_cRefs;
|
|
if (cRefs == 0)
|
|
delete this;
|
|
|
|
return cRefs;
|
|
}
|
|
|
|
|
|
HRESULT UlsLdap_CLocalUser::
|
|
Register ( ULONG *puRespID, SERVER_INFO *pServerInfo, LDAP_USERINFO *pInfo )
|
|
{
|
|
MyAssert (puRespID != NULL);
|
|
MyAssert (pInfo != NULL);
|
|
|
|
MyAssert ( pServerInfo->pszServerName != NULL &&
|
|
pServerInfo->pszServerName[0] != TEXT ('\0'));
|
|
MyAssert ( pServerInfo->pszBaseDN != NULL &&
|
|
pServerInfo->pszBaseDN[0] != TEXT ('\0'));
|
|
|
|
// cache the server info
|
|
HRESULT hr = ::IlsCopyServerInfo (&m_ServerInfo, pServerInfo);
|
|
if (hr != S_OK)
|
|
return hr;
|
|
|
|
// cache user info
|
|
hr = CacheUserInfo (pInfo);
|
|
if (hr != S_OK)
|
|
return hr;
|
|
|
|
// get ip address
|
|
m_dwIPAddress = 0;
|
|
hr = ::GetLocalIPAddress (&m_dwIPAddress);
|
|
if (hr != S_OK)
|
|
return hr;
|
|
|
|
// Create IP address string
|
|
//
|
|
m_UserInfo.apszStdAttrValues[ENUM_USERATTR_IP_ADDRESS] = &m_UserInfo.szIPAddress[0];
|
|
::GetLongString (m_dwIPAddress, &m_UserInfo.szIPAddress[0]);
|
|
|
|
// Create client signature string
|
|
//
|
|
m_UserInfo.apszStdAttrValues[ENUM_USERATTR_CLIENT_SIG] = &m_UserInfo.szClientSig[0];
|
|
::GetLongString (g_dwClientSig, &m_UserInfo.szClientSig[0]);
|
|
|
|
// Create TTL string
|
|
//
|
|
m_UserInfo.apszStdAttrValues[ENUM_USERATTR_TTL] = &m_UserInfo.szTTL[0];
|
|
::GetLongString (m_uTTL, &m_UserInfo.szTTL[0]);
|
|
|
|
// ideally, o= and c= should be read in from registiry
|
|
// but for now, we simply hard code it
|
|
m_UserInfo.apszStdAttrValues[ENUM_USERATTR_OBJECT_CLASS] = (TCHAR *) &c_szRTPerson[0];
|
|
m_UserInfo.apszStdAttrValues[ENUM_USERATTR_O] = (TCHAR *) &c_szDefO[0];
|
|
#ifdef USE_DEFAULT_COUNTRY
|
|
m_UserInfo.apszStdAttrValues[ENUM_USERATTR_C] = (TCHAR *) &c_szDefC[0];
|
|
#endif
|
|
|
|
// build DN
|
|
hr = BuildDN ();
|
|
if (hr != S_OK)
|
|
return hr;
|
|
|
|
// build refreh filter
|
|
m_pszRefreshFilter = UserCreateRefreshFilter (m_UserInfo.apszStdAttrValues[ENUM_USERATTR_CN]);
|
|
if (m_pszRefreshFilter == NULL)
|
|
return ULS_E_MEMORY;
|
|
|
|
// build modify array for ldap_add()
|
|
LDAPMod **ppMod = NULL;
|
|
hr = CreateRegisterModArr (&ppMod);
|
|
if (hr != S_OK)
|
|
return hr;
|
|
MyAssert (ppMod != NULL);
|
|
|
|
// so far, we are done with local preparation
|
|
|
|
// get the connection object
|
|
UlsLdap_CSession *pSession = NULL;
|
|
hr = g_pSessionContainer->GetSession (&pSession, &m_ServerInfo);
|
|
if (hr != S_OK)
|
|
{
|
|
MemFree (ppMod);
|
|
return hr;
|
|
}
|
|
MyAssert (pSession != NULL);
|
|
|
|
// get the ldap session
|
|
LDAP *ld = pSession->GetLd ();
|
|
MyAssert (ld != NULL);
|
|
|
|
// send the data over the wire
|
|
ULONG uMsgID = ldap_add (ld, GetDN (), ppMod);
|
|
MemFree (ppMod);
|
|
if (uMsgID == -1)
|
|
{
|
|
hr = ::LdapError2Hresult (ld->ld_errno);
|
|
pSession->Disconnect ();
|
|
return hr;
|
|
}
|
|
|
|
// construct a pending info
|
|
PENDING_INFO PendingInfo;
|
|
::FillDefPendingInfo (&PendingInfo, ld, uMsgID, INVALID_MSG_ID);
|
|
PendingInfo.uLdapResType = LDAP_RES_ADD;
|
|
PendingInfo.uNotifyMsg = WM_ULS_REGISTER_USER;
|
|
PendingInfo.hObject = (HANDLE) this;
|
|
|
|
// queue it
|
|
hr = g_pPendingQueue->EnterRequest (pSession, &PendingInfo);
|
|
if (hr != S_OK)
|
|
{
|
|
ldap_abandon (ld, uMsgID);
|
|
pSession->Disconnect ();
|
|
MyAssert (FALSE);
|
|
}
|
|
|
|
*puRespID = PendingInfo.uRespID;
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT UlsLdap_CLocalUser::
|
|
UnRegister ( ULONG *puRespID )
|
|
{
|
|
MyAssert (puRespID != NULL);
|
|
|
|
// Make sure that there is not refresh scheduled for this object
|
|
//
|
|
if (g_pRefreshScheduler != NULL)
|
|
{
|
|
g_pRefreshScheduler->RemoveUserObject (this);
|
|
}
|
|
else
|
|
{
|
|
MyAssert (FALSE);
|
|
}
|
|
|
|
// Unregister it locally
|
|
//
|
|
if (! IsRegRemotely ())
|
|
{
|
|
*puRespID = ::GetUniqueNotifyID ();
|
|
SetRegNone ();
|
|
PostMessage (g_hWndNotify, WM_ULS_UNREGISTER_USER, *puRespID, S_OK);
|
|
return S_OK;
|
|
}
|
|
|
|
SetRegNone ();
|
|
|
|
// Get the session object
|
|
//
|
|
UlsLdap_CSession *pSession = NULL;
|
|
HRESULT hr = g_pSessionContainer->GetSession (&pSession, &m_ServerInfo);
|
|
if (hr != S_OK)
|
|
return hr;
|
|
MyAssert (pSession != NULL);
|
|
|
|
// Get the ldap session
|
|
//
|
|
LDAP *ld = pSession->GetLd ();
|
|
MyAssert (ld != NULL);
|
|
|
|
// LONCHANC: notify global user object of this unregister user
|
|
|
|
|
|
// send the data over the wire
|
|
ULONG uMsgID = ldap_delete (ld, GetDN ());
|
|
if (uMsgID == -1)
|
|
{
|
|
hr = ::LdapError2Hresult (ld->ld_errno);
|
|
pSession->Disconnect ();
|
|
return hr;
|
|
}
|
|
|
|
// construct a pending info
|
|
PENDING_INFO PendingInfo;
|
|
::FillDefPendingInfo (&PendingInfo, ld, uMsgID, INVALID_MSG_ID);
|
|
PendingInfo.uLdapResType = LDAP_RES_DELETE;
|
|
PendingInfo.uNotifyMsg = WM_ULS_UNREGISTER_USER;
|
|
|
|
// queue it
|
|
hr = g_pPendingQueue->EnterRequest (pSession, &PendingInfo);
|
|
if (hr != S_OK)
|
|
{
|
|
ldap_abandon (ld, uMsgID);
|
|
pSession->Disconnect ();
|
|
MyAssert (FALSE);
|
|
}
|
|
|
|
*puRespID = PendingInfo.uRespID;
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT UlsLdap_CLocalUser::
|
|
SetStdAttrs ( ULONG *puRespID, LDAP_USERINFO *pInfo )
|
|
{
|
|
MyAssert (puRespID != NULL);
|
|
MyAssert (pInfo != NULL);
|
|
|
|
ULONG uMsgID_modify, uMsgID_modrdn;
|
|
UlsLdap_CSession *pSession;
|
|
LDAP *ld;
|
|
HRESULT hr;
|
|
|
|
// Get the session object
|
|
//
|
|
hr = g_pSessionContainer->GetSession (&pSession, GetServerInfo ());
|
|
if (hr != S_OK)
|
|
return hr;
|
|
MyAssert (pSession != NULL);
|
|
|
|
// Get the ldap session
|
|
//
|
|
ld = pSession->GetLd ();
|
|
MyAssert (ld != NULL);
|
|
|
|
// Change cn?
|
|
//
|
|
if (pInfo->uOffsetEMailName != 0)
|
|
{
|
|
// Cache user info such that cn is refreshed
|
|
//
|
|
hr = CacheUserInfo (pInfo);
|
|
if (hr != S_OK)
|
|
{
|
|
pSession->Disconnect ();
|
|
return hr;
|
|
}
|
|
|
|
// We have to use ldap_modrdn to modify cn and this must be
|
|
// done before any other attribute changes
|
|
//
|
|
uMsgID_modrdn = ldap_modrdn2 (
|
|
ld, GetDN (),
|
|
m_UserInfo.apszStdAttrValues[ENUM_USERATTR_CN],
|
|
1);
|
|
if (uMsgID_modrdn == -1)
|
|
{
|
|
pSession->Disconnect ();
|
|
hr = ::LdapError2Hresult (ld->ld_errno);
|
|
return hr;
|
|
}
|
|
|
|
// Update DN
|
|
//
|
|
BuildDN ();
|
|
}
|
|
else
|
|
{
|
|
uMsgID_modrdn = INVALID_MSG_ID;
|
|
}
|
|
|
|
// Set standard attributes
|
|
//
|
|
hr = UlsLdap_CStdAttrs::SetStdAttrs ( NULL,
|
|
&uMsgID_modify,
|
|
0,
|
|
(VOID *) pInfo,
|
|
GetServerInfo (),
|
|
GetDN ());
|
|
if (hr != S_OK)
|
|
{
|
|
if (uMsgID_modrdn != INVALID_MSG_ID)
|
|
{
|
|
ldap_abandon (ld, uMsgID_modrdn);
|
|
pSession->Disconnect ();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
// Construct a pending info
|
|
//
|
|
PENDING_INFO PendingInfo;
|
|
if (uMsgID_modrdn == INVALID_MSG_ID)
|
|
::FillDefPendingInfo (&PendingInfo, ld, uMsgID_modify, INVALID_MSG_ID);
|
|
else
|
|
::FillDefPendingInfo (&PendingInfo, ld, uMsgID_modrdn, uMsgID_modify);
|
|
PendingInfo.uLdapResType = LDAP_RES_MODIFY;
|
|
PendingInfo.uNotifyMsg = WM_ULS_SET_USER_INFO;
|
|
PendingInfo.hObject = (HANDLE) this; // for DN rollback
|
|
|
|
// Queue it
|
|
//
|
|
hr = g_pPendingQueue->EnterRequest (pSession, &PendingInfo);
|
|
if (hr != S_OK)
|
|
{
|
|
if (uMsgID_modrdn != INVALID_MSG_ID)
|
|
{
|
|
ldap_abandon (ld, uMsgID_modrdn);
|
|
pSession->Disconnect ();
|
|
}
|
|
ldap_abandon (ld, uMsgID_modify);
|
|
MyAssert (FALSE);
|
|
}
|
|
|
|
*puRespID = PendingInfo.uRespID;
|
|
return hr;
|
|
}
|
|
|
|
|
|
VOID UlsLdap_CLocalUser::
|
|
RollbackDN ( VOID )
|
|
{
|
|
if (m_pszOldDN != NULL)
|
|
{
|
|
MemFree (m_pszDN);
|
|
m_pszDN = m_pszOldDN;
|
|
m_pszOldDN = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT UlsLdap_CLocalUser::
|
|
UpdateIPAddress ( BOOL fPrimary )
|
|
{
|
|
// Update cached ip address
|
|
//
|
|
HRESULT hr = ::GetLocalIPAddress (&m_dwIPAddress);
|
|
if (hr != S_OK)
|
|
return hr;
|
|
|
|
// Update the ip address string
|
|
//
|
|
::GetLongString (m_dwIPAddress, &m_UserInfo.szIPAddress[0]);
|
|
|
|
// Update ip address info on the server ONLY if primary
|
|
//
|
|
if (! fPrimary)
|
|
return hr;
|
|
|
|
// Update IP address on the server
|
|
//
|
|
return ::IlsUpdateIPAddress ( GetServerInfo (),
|
|
GetDN (),
|
|
(TCHAR *) c_apszUserStdAttrNames[ENUM_USERATTR_IP_ADDRESS],
|
|
&m_UserInfo.szIPAddress[0],
|
|
ISBU_MODOP_MODIFY_USER,
|
|
GetPrefixCount (),
|
|
GetPrefixString ());
|
|
}
|
|
|
|
|
|
/* ---------- protected methods ----------- */
|
|
|
|
|
|
HRESULT UlsLdap_CLocalUser::
|
|
SendRefreshMsg ( VOID )
|
|
{
|
|
if (m_pszRefreshFilter == NULL)
|
|
return ULS_E_POINTER;
|
|
|
|
// Get local ip address
|
|
//
|
|
DWORD dwIPAddress = 0;
|
|
HRESULT hr = ::GetLocalIPAddress (&dwIPAddress);
|
|
if (hr != S_OK)
|
|
{
|
|
MyDebugMsg ((ZONE_KA, "KA: cannot get my ip address\r\n"));
|
|
return hr;
|
|
}
|
|
|
|
// If dwIPAddress is 0, then we are not on the network any more
|
|
// start relogon process
|
|
//
|
|
if (dwIPAddress == 0)
|
|
{
|
|
MyDebugMsg ((ZONE_KA, "KA: my ip address is null\r\n"));
|
|
|
|
// Indicate that I am not connected to the server anymore
|
|
//
|
|
SetRegLocally ();
|
|
|
|
// Second, notify this app of the network being down
|
|
//
|
|
PostMessage (g_hWndHidden, WM_ULS_NETWORK_DOWN, TRUE, (LPARAM) this);
|
|
|
|
// Report error
|
|
//
|
|
return ULS_E_NETWORK_DOWN;
|
|
;
|
|
}
|
|
else
|
|
// If dwIPAddress and m_dwIPAddress, alert
|
|
//
|
|
if (dwIPAddress != m_dwIPAddress)
|
|
{
|
|
// Notify the com to start changing ip address
|
|
// the actual change can happen later
|
|
//
|
|
PostMessage (g_hWndHidden, WM_ULS_IP_ADDRESS_CHANGED, TRUE, (LPARAM) this);
|
|
}
|
|
|
|
// get the connection object
|
|
UlsLdap_CSession *pSession = NULL;
|
|
hr = g_pSessionContainer->GetSession (&pSession, &m_ServerInfo);
|
|
if (hr != S_OK)
|
|
{
|
|
MyDebugMsg ((ZONE_KA, "KA: network down, hr=0x%lX\r\n", hr));
|
|
|
|
// Indicate that I am not connected to the server anymore
|
|
//
|
|
SetRegLocally ();
|
|
|
|
// Second, notify the com of network down
|
|
//
|
|
PostMessage (g_hWndHidden, WM_ULS_NETWORK_DOWN, TRUE, (LPARAM) this);
|
|
|
|
// Report error
|
|
//
|
|
return ULS_E_NETWORK_DOWN;
|
|
}
|
|
MyAssert (pSession != NULL);
|
|
|
|
// get the ldap session
|
|
LDAP *ld = pSession->GetLd ();
|
|
MyAssert (ld != NULL);
|
|
|
|
// Set attributes to return
|
|
//
|
|
TCHAR *apszAttrNames[3];
|
|
apszAttrNames[0] = STR_CN;
|
|
apszAttrNames[1] = (TCHAR *) c_apszUserStdAttrNames[ENUM_USERATTR_TTL];
|
|
apszAttrNames[2] = NULL;
|
|
|
|
// Update options in ld
|
|
//
|
|
ld->ld_sizelimit = 0; // no limit in the num of entries to return
|
|
ld->ld_timelimit = 0; // no limit on the time to spend on the search
|
|
ld->ld_deref = LDAP_DEREF_ALWAYS;
|
|
|
|
// Send search query
|
|
//
|
|
MyDebugMsg ((ZONE_KA, "KA: calling ldap_search()...\r\n"));
|
|
ULONG uMsgID = ::ldap_search (ld, (TCHAR *) &c_szDefUserBaseDN[0], // base DN
|
|
LDAP_SCOPE_BASE, // scope
|
|
m_pszRefreshFilter,
|
|
&apszAttrNames[0], // attrs[]
|
|
0 // both type and value
|
|
);
|
|
if (uMsgID == -1)
|
|
{
|
|
MyDebugMsg ((ZONE_KA, "KA: ldap_search() failed\r\n"));
|
|
hr = ::LdapError2Hresult (ld->ld_errno);
|
|
pSession->Disconnect ();
|
|
return hr;
|
|
}
|
|
|
|
// Let's wait for the result
|
|
//
|
|
LDAP_TIMEVAL TimeVal;
|
|
TimeVal.tv_usec = 0;
|
|
TimeVal.tv_sec = (m_ServerInfo.nTimeout != 0) ?
|
|
m_ServerInfo.nTimeout :
|
|
90;
|
|
LDAPMessage *pLdapMsg = NULL;
|
|
INT ResultType = ::ldap_result (ld, uMsgID, 0, &TimeVal, &pLdapMsg);
|
|
|
|
// Deal with timeout or error
|
|
//
|
|
if (ResultType != LDAP_RES_SEARCH_ENTRY &&
|
|
ResultType != LDAP_RES_SEARCH_RESULT)
|
|
{
|
|
MyDebugMsg ((ZONE_KA, "KA: result type mismatches!\r\n"));
|
|
hr = ULS_E_TIMEOUT;
|
|
goto MyExit;
|
|
}
|
|
|
|
if (pLdapMsg != NULL)
|
|
{
|
|
switch (pLdapMsg->lm_returncode)
|
|
{
|
|
case LDAP_NO_SUCH_OBJECT:
|
|
MyDebugMsg ((ZONE_KA, "KA: no such object!\r\n"));
|
|
|
|
// Indicate that I am not connected to the server anymore
|
|
//
|
|
SetRegLocally ();
|
|
|
|
// Second, notify this app to relogon
|
|
//
|
|
PostMessage (g_hWndHidden, WM_ULS_NEED_RELOGON, TRUE, (LPARAM) this);
|
|
|
|
// Report error
|
|
//
|
|
hr = ULS_E_NEED_RELOGON;
|
|
break;
|
|
|
|
case LDAP_SUCCESS:
|
|
// Get the new refresh period
|
|
//
|
|
hr = ::IlsParseRefreshPeriod (
|
|
ld,
|
|
pLdapMsg,
|
|
c_apszUserStdAttrNames[ENUM_USERATTR_TTL],
|
|
&m_uTTL);
|
|
break;
|
|
|
|
default:
|
|
MyDebugMsg ((ZONE_KA, "KA: unknown lm_returncode=%ld\r\n", pLdapMsg->lm_returncode));
|
|
MyAssert (FALSE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
MyExit:
|
|
|
|
// Free message
|
|
//
|
|
if (pLdapMsg != NULL)
|
|
ldap_msgfree (pLdapMsg);
|
|
|
|
// Free up the session
|
|
//
|
|
pSession->Disconnect ();
|
|
return hr;
|
|
}
|
|
|
|
|
|
/* ---------- private methods ----------- */
|
|
|
|
|
|
HRESULT UlsLdap_CLocalUser::
|
|
CreateRegisterModArr ( LDAPMod ***pppMod )
|
|
{
|
|
if (pppMod == NULL)
|
|
return ULS_E_POINTER;
|
|
|
|
ULONG cAttrs = COUNT_ENUM_USERATTR;
|
|
ULONG cbMod = ::IlsCalcModifyListSize (cAttrs);
|
|
*pppMod = (LDAPMod **) MemAlloc (cbMod);
|
|
if (*pppMod == NULL)
|
|
return ULS_E_MEMORY;
|
|
|
|
LDAPMod *pMod;
|
|
for (ULONG i = 0; i < cAttrs; i++)
|
|
{
|
|
pMod = ::IlsGetModifyListMod (pppMod, cAttrs, i);
|
|
(*pppMod)[i] = pMod;
|
|
pMod->mod_op = LDAP_MOD_ADD;
|
|
|
|
FillModArrAttr (pMod, i);
|
|
}
|
|
|
|
// the following overwrote givenname attribute
|
|
// ::IlsFixUpModOp ((*pppMod)[0], LDAP_MOD_ADD);
|
|
(*pppMod)[cAttrs] = NULL;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT UlsLdap_CLocalUser::
|
|
CreateSetStdAttrsModArr ( LDAPMod ***pppMod )
|
|
{
|
|
MyAssert (pppMod != NULL);
|
|
DWORD dwFlags = m_UserInfo.dwFlags;
|
|
|
|
HRESULT hr;
|
|
ULONG cTotal = 0;
|
|
hr = ::FillDefStdAttrsModArr ( pppMod,
|
|
dwFlags,
|
|
COUNT_ENUM_USERINFO,
|
|
&cTotal,
|
|
ISBU_MODOP_MODIFY_USER,
|
|
GetPrefixCount (),
|
|
GetPrefixString ());
|
|
if (hr != S_OK)
|
|
return hr;
|
|
|
|
// Start indexing
|
|
//
|
|
ULONG i = GetPrefixCount ();
|
|
|
|
// Fill in standard attributes
|
|
//
|
|
if (dwFlags & USEROBJ_F_FIRST_NAME)
|
|
FillModArrAttr ((*pppMod)[i++], ENUM_USERATTR_FIRST_NAME);
|
|
|
|
if (dwFlags & USEROBJ_F_LAST_NAME)
|
|
FillModArrAttr ((*pppMod)[i++], ENUM_USERATTR_LAST_NAME);
|
|
|
|
if (dwFlags & USEROBJ_F_EMAIL_NAME)
|
|
FillModArrAttr ((*pppMod)[i++], ENUM_USERATTR_EMAIL_NAME);
|
|
|
|
if (dwFlags & USEROBJ_F_CITY_NAME)
|
|
FillModArrAttr ((*pppMod)[i++], ENUM_USERATTR_CITY_NAME);
|
|
|
|
if (dwFlags & USEROBJ_F_COUNTRY_NAME)
|
|
FillModArrAttr ((*pppMod)[i++], ENUM_USERATTR_COUNTRY_NAME);
|
|
|
|
if (dwFlags & USEROBJ_F_COMMENT)
|
|
FillModArrAttr ((*pppMod)[i++], ENUM_USERATTR_COMMENT);
|
|
|
|
if (dwFlags & USEROBJ_F_IP_ADDRESS)
|
|
FillModArrAttr ((*pppMod)[i++], ENUM_USERATTR_IP_ADDRESS);
|
|
|
|
if (dwFlags & USEROBJ_F_FLAGS)
|
|
FillModArrAttr ((*pppMod)[i++], ENUM_USERATTR_FLAGS);
|
|
|
|
MyAssert (i == cTotal);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
VOID UlsLdap_CLocalUser::
|
|
FillModArrAttr ( LDAPMod *pMod, LONG AttrIdx )
|
|
{
|
|
pMod->mod_type = (TCHAR *) c_apszUserStdAttrNames[AttrIdx];
|
|
|
|
// single valued attr
|
|
TCHAR **ppsz = (TCHAR **) (pMod + 1);
|
|
pMod->mod_values = ppsz;
|
|
*ppsz++ = (m_UserInfo.apszStdAttrValues[AttrIdx] != NULL) ?
|
|
m_UserInfo.apszStdAttrValues[AttrIdx] :
|
|
(TCHAR *) &c_szEmptyString[0];
|
|
|
|
*ppsz = NULL;
|
|
}
|
|
|
|
|
|
HRESULT UlsLdap_CLocalUser::
|
|
CacheInfo ( VOID *pInfo )
|
|
{
|
|
return CacheUserInfo ((LDAP_USERINFO *) pInfo);
|
|
}
|
|
|
|
|
|
HRESULT UlsLdap_CLocalUser::
|
|
CacheUserInfo ( LDAP_USERINFO *pInfo )
|
|
{
|
|
ZeroMemory (&m_UserInfo, sizeof (m_UserInfo));
|
|
TCHAR *pszName;
|
|
|
|
if (pInfo->uOffsetName != INVALID_OFFSET)
|
|
{
|
|
pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetName);
|
|
m_UserInfo.apszStdAttrValues[ENUM_USERATTR_CN] = pszName;
|
|
// m_UserInfo.dwFlags |= USEROBJ_F_NAME;
|
|
}
|
|
|
|
if (pInfo->uOffsetFirstName != INVALID_OFFSET)
|
|
{
|
|
pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetFirstName);
|
|
m_UserInfo.apszStdAttrValues[ENUM_USERATTR_FIRST_NAME] = pszName;
|
|
m_UserInfo.dwFlags |= USEROBJ_F_FIRST_NAME;
|
|
}
|
|
|
|
if (pInfo->uOffsetLastName != INVALID_OFFSET)
|
|
{
|
|
pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetLastName);
|
|
m_UserInfo.apszStdAttrValues[ENUM_USERATTR_LAST_NAME] = pszName;
|
|
m_UserInfo.dwFlags |= USEROBJ_F_LAST_NAME;
|
|
}
|
|
|
|
if (pInfo->uOffsetEMailName != INVALID_OFFSET)
|
|
{
|
|
pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetEMailName);
|
|
m_UserInfo.apszStdAttrValues[ENUM_USERATTR_EMAIL_NAME] = pszName;
|
|
m_UserInfo.dwFlags |= USEROBJ_F_EMAIL_NAME;
|
|
}
|
|
|
|
if (pInfo->uOffsetCityName != INVALID_OFFSET)
|
|
{
|
|
pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetCityName);
|
|
m_UserInfo.apszStdAttrValues[ENUM_USERATTR_CITY_NAME] = pszName;
|
|
m_UserInfo.dwFlags |= USEROBJ_F_CITY_NAME;
|
|
}
|
|
|
|
if (pInfo->uOffsetCountryName != INVALID_OFFSET)
|
|
{
|
|
pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetCountryName);
|
|
m_UserInfo.apszStdAttrValues[ENUM_USERATTR_COUNTRY_NAME] = pszName;
|
|
m_UserInfo.dwFlags |= USEROBJ_F_COUNTRY_NAME;
|
|
}
|
|
|
|
if (pInfo->uOffsetComment != INVALID_OFFSET)
|
|
{
|
|
pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetComment);
|
|
m_UserInfo.apszStdAttrValues[ENUM_USERATTR_COMMENT] = pszName;
|
|
m_UserInfo.dwFlags |= USEROBJ_F_COMMENT;
|
|
}
|
|
|
|
if (pInfo->uOffsetIPAddress != INVALID_OFFSET)
|
|
{
|
|
pszName = (TCHAR *) (((BYTE *) pInfo) + pInfo->uOffsetIPAddress);
|
|
m_UserInfo.apszStdAttrValues[ENUM_USERATTR_IP_ADDRESS] = pszName;
|
|
m_UserInfo.dwFlags |= USEROBJ_F_IP_ADDRESS;
|
|
}
|
|
|
|
if (pInfo->dwFlags != INVALID_USER_FLAGS)
|
|
{
|
|
::GetLongString (pInfo->dwFlags, &m_UserInfo.szFlags[0]);
|
|
m_UserInfo.apszStdAttrValues[ENUM_USERATTR_FLAGS] = &m_UserInfo.szFlags[0];
|
|
m_UserInfo.dwFlags |= USEROBJ_F_FLAGS;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT UlsLdap_CLocalUser::
|
|
BuildDN ( VOID )
|
|
{
|
|
MyAssert (m_UserInfo.apszStdAttrValues[ENUM_USERATTR_CN] != NULL);
|
|
|
|
TCHAR szDN[MAX_DN_LENGTH];
|
|
szDN[0] = TEXT ('\0');
|
|
|
|
TCHAR *pszDN = &szDN[0];
|
|
|
|
if (m_UserInfo.apszStdAttrValues[ENUM_USERATTR_CN] != NULL)
|
|
{
|
|
wsprintf (pszDN, TEXT ("%s=%s"),
|
|
STR_CN, m_UserInfo.apszStdAttrValues[ENUM_USERATTR_CN]);
|
|
pszDN += lstrlen (pszDN);
|
|
}
|
|
|
|
if (m_UserInfo.apszStdAttrValues[ENUM_USERATTR_O] != NULL)
|
|
{
|
|
wsprintf (pszDN, TEXT (", %s=%s"),
|
|
STR_O, m_UserInfo.apszStdAttrValues[ENUM_USERATTR_O]);
|
|
pszDN += lstrlen (pszDN);
|
|
}
|
|
|
|
if (m_UserInfo.apszStdAttrValues[ENUM_USERATTR_C] != NULL)
|
|
{
|
|
wsprintf (pszDN, TEXT (", %s=%s"),
|
|
STR_C, m_UserInfo.apszStdAttrValues[ENUM_USERATTR_C]);
|
|
pszDN += lstrlen (pszDN);
|
|
}
|
|
|
|
wsprintf (pszDN, TEXT (", %s"), &c_szDefUserBaseDN[0]);
|
|
|
|
TCHAR *psz = My_strdup (&szDN[0]);
|
|
if (psz == NULL)
|
|
return ULS_E_MEMORY;
|
|
|
|
MemFree (m_pszOldDN);
|
|
m_pszOldDN = m_pszDN;
|
|
m_pszDN = psz;
|
|
return S_OK;
|
|
}
|
|
|
|
|