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.
 
 
 
 
 
 

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