windows-nt/Source/XPSP1/NT/enduser/netmeeting/ulsldap/spils.cpp
2020-09-26 16:20:57 +08:00

1077 lines
22 KiB
C++

/* ----------------------------------------------------------------------
Module: ULS.DLL (Service Provider)
File: spils.cpp
Content: This file contains the ILS specifics.
History:
12/10/96 Chu, Lon-Chan [lonchanc]
Created.
Copyright (c) Microsoft Corporation 1996-1997
---------------------------------------------------------------------- */
#include "ulsp.h"
#include "spinc.h"
#include "winsock.h"
#include "ping.h"
// Constant string for ISBU's special modify-operation attribute
//
const TCHAR c_szModOp[] = { TEXT ('s'), TEXT ('m'), TEXT ('o'), TEXT ('d'),
TEXT ('o'), TEXT ('p'), TEXT ('\0'),
TEXT ('0'), TEXT ('\0')}; //TEXT ("smodop\0000");
ULONG g_cbUserPrefix = sizeof (c_szModOp);
TCHAR *g_pszUserPrefix = NULL;
ULONG g_cbMtgPrefix = sizeof (c_szModOp);
TCHAR *g_pszMtgPrefix = NULL;
CPing *g_pPing = NULL;
HRESULT
IlsInitialize ( VOID )
{
// Allocate the ping object
//
g_pPing = new CPing;
if (g_pPing == NULL)
return ILS_E_MEMORY;
// Allocate user prefix
//
g_pszUserPrefix = (TCHAR *) MemAlloc (g_cbUserPrefix);
if (g_pszUserPrefix == NULL)
return ILS_E_MEMORY;
// Fill in user prefix string
//
TCHAR *psz = g_pszUserPrefix;
lstrcpy (psz, &c_szModOp[0]);
psz += lstrlen (psz) + 1;
lstrcpy (psz, TEXT ("0"));
// Allocate mtg prefix
//
g_pszMtgPrefix = (TCHAR *) MemAlloc (g_cbMtgPrefix);
if (g_pszMtgPrefix == NULL)
{
MemFree (g_pszUserPrefix);
g_pszUserPrefix = NULL;
return ILS_E_MEMORY;
}
// Fill in mtg prefix string
//
psz = g_pszMtgPrefix;
lstrcpy (psz, &c_szModOp[0]);
psz += lstrlen (psz) + 1;
lstrcpy (psz, TEXT ("0"));
return S_OK;
}
HRESULT
IlsCleanup ( VOID )
{
// Free the ping object
//
if (g_pPing != NULL)
{
delete g_pPing;
g_pPing = NULL;
}
// Free user prefix string
//
MemFree (g_pszUserPrefix);
g_pszUserPrefix = NULL;
// Free mtg prefix string
//
MemFree (g_pszMtgPrefix);
g_pszMtgPrefix = NULL;
return S_OK;
}
ULONG
IlsCalcModifyListSize ( ULONG cAttrs )
{
ULONG cbSize;
// array itself
cbSize = (cAttrs + 1) * sizeof (LDAPMod *);
// array elements
cbSize += cAttrs * sizeof (LDAPMod);
// single valued attribute requires two pointers
cbSize += cAttrs * 2 * sizeof (TCHAR *);
return cbSize;
}
LDAPMod *
IlsGetModifyListMod ( LDAPMod ***pppMod, ULONG cAttrs, LONG AttrIdx )
{
return (LDAPMod *) (((BYTE *) *pppMod) +
(cAttrs + 1) * sizeof (LDAPMod *) +
AttrIdx * (sizeof (LDAPMod) + 2 * sizeof (TCHAR *)));
}
VOID
IlsFillModifyListItem (
LDAPMod *pMod,
TCHAR *pszAttrName,
TCHAR *pszAttrValue )
{
MyAssert (pMod != NULL);
MyAssert (pszAttrName != NULL);
// Set attribute name
//
pMod->mod_type = pszAttrName;
// Set single valued attribute value
//
TCHAR **ppsz = (TCHAR **) (pMod + 1);
pMod->mod_values = ppsz;
*ppsz++ = (pszAttrValue != NULL) ? pszAttrValue : STR_EMPTY;
// Set null string to terminate this array of values
//
*ppsz = NULL;
}
VOID
IlsFillModifyListForAnyAttrs (
LDAPMod *apMod[],
ULONG *puIndex,
ANY_ATTRS *pAnyAttrs )
{
LDAPMod *pMod;
TCHAR *pszName, *pszValue;
ULONG i = *puIndex, j;
// Put in extended attributes to add
//
pszName = pAnyAttrs->pszAttrsToAdd;
for (j = 0; j < pAnyAttrs->cAttrsToAdd; j++)
{
pMod = apMod[i++];
pMod->mod_op = LDAP_MOD_ADD;
pszValue = pszName + lstrlen (pszName) + 1;
IlsFillModifyListItem (pMod, pszName, pszValue);
pszName = pszValue + lstrlen (pszValue) + 1;
}
// Put in extended attributes to modify
//
pszName = pAnyAttrs->pszAttrsToModify;
for (j = 0; j < pAnyAttrs->cAttrsToModify; j++)
{
pMod = apMod[i++];
pMod->mod_op = LDAP_MOD_REPLACE;
pszValue = pszName + lstrlen (pszName) + 1;
IlsFillModifyListItem (pMod, pszName, pszValue);
pszName = pszValue + lstrlen (pszValue) + 1;
}
// Put in extended attributes to remove
//
pszName = pAnyAttrs->pszAttrsToRemove;
for (j = 0; j < pAnyAttrs->cAttrsToRemove; j++)
{
pMod = apMod[i++];
pMod->mod_op = LDAP_MOD_DELETE;
IlsFillModifyListItem (pMod, pszName, NULL);
pszName = pszName + lstrlen (pszName) + 1;
}
// Return the running index
//
*puIndex = i;
}
TCHAR c_szModOp_AddApp[] = TEXT ("0");
TCHAR c_szModOp_DeleteApp[] = TEXT ("1");
TCHAR c_szModOp_ModifyUser[] = TEXT ("2");
TCHAR c_szModOp_ModifyApp[] = TEXT ("3");
VOID
IlsFixUpModOp ( LDAPMod *pMod, LONG LdapModOp, LONG IsbuModOp )
{
MyAssert (pMod != NULL);
pMod->mod_op = LdapModOp;
// pMod->mod_op = LDAP_MOD_ADD; // lonchanc: MUST MUST MUST
pMod->mod_type = (TCHAR *) &c_szModOp[0];
pMod->mod_values = (TCHAR **) (pMod + 1);
switch (IsbuModOp)
{
case ISBU_MODOP_ADD_APP:
*(pMod->mod_values) = &c_szModOp_AddApp[0];
break;
case ISBU_MODOP_DELETE_APP:
*(pMod->mod_values) = &c_szModOp_DeleteApp[0];
break;
case ISBU_MODOP_MODIFY_USER:
*(pMod->mod_values) = &c_szModOp_ModifyUser[0];
break;
case ISBU_MODOP_MODIFY_APP:
*(pMod->mod_values) = &c_szModOp_ModifyApp[0];
break;
default:
MyAssert (FALSE);
break;
}
}
HRESULT
IlsParseRefreshPeriod (
LDAP *ld,
LDAPMessage *pLdapMsg,
const TCHAR *pszTtlAttrName,
ULONG *puTTL )
{
MyAssert (ld != NULL);
MyAssert (pLdapMsg != NULL);
MyAssert (pszTtlAttrName != NULL);
MyAssert (puTTL != NULL);
HRESULT hr;
ULONG uRefreshPeriod;
ULONG tcRefreshPeriod;
// Get the first entry
//
LDAPMessage *pEntry = ldap_first_entry (ld, pLdapMsg);
if (pEntry == NULL)
{
MyAssert (FALSE);
hr = ILS_E_MEMORY;
goto MyExit;
}
// Get the sTTL attribute
//
TCHAR **ppszAttrVal;
ppszAttrVal = my_ldap_get_values (ld, pEntry, (TCHAR *) pszTtlAttrName);
if (ppszAttrVal == NULL || *ppszAttrVal == NULL)
{
MyAssert (FALSE);
hr = ILS_E_MEMORY;
goto MyExit;
}
// Convert string to long
//
uRefreshPeriod = ::GetStringLong (*ppszAttrVal);
// Reserve two-minute overhead
//
if (uRefreshPeriod > ILS_DEF_REFRESH_MARGIN_MINUTE)
uRefreshPeriod -= ILS_DEF_REFRESH_MARGIN_MINUTE;
// Make sure we have a safe, reasonable refresh period at least
//
if (uRefreshPeriod < ILS_DEF_REFRESH_MARGIN_MINUTE)
uRefreshPeriod = ILS_DEF_REFRESH_MARGIN_MINUTE;
// Convert min to ms
//
tcRefreshPeriod = Minute2TickCount (uRefreshPeriod);
// Free the attribute value
//
ldap_value_free (ppszAttrVal);
// Update ttl
//
*puTTL = uRefreshPeriod; // in unit of minute
hr = S_OK;
MyExit:
if (hr != S_OK)
{
MyAssert (FALSE);
}
return hr;
}
HRESULT
IlsUpdateOneAttr (
SERVER_INFO *pServerInfo,
TCHAR *pszDN,
TCHAR *pszAttrName,
TCHAR *pszAttrValue,
LONG nModifyMagic,
ULONG cPrefix,
TCHAR *pszPrefix,
SP_CSession **ppSession, // output
ULONG *puMsgID ) // output
{
MyAssert (pServerInfo != NULL);
MyAssert (pszDN != NULL);
MyAssert (pszAttrName != NULL);
MyAssert (pszAttrValue != NULL);
MyAssert ( nModifyMagic == ISBU_MODOP_MODIFY_USER ||
nModifyMagic == ISBU_MODOP_MODIFY_APP);
MyAssert (ppSession != NULL);
MyAssert (puMsgID != NULL);
// Build modify array for ldap_modify()
//
LDAP *ld;
LDAPMod **ppMod = NULL;
ULONG cTotal = 0;
HRESULT hr = IlsFillDefStdAttrsModArr (&ppMod,
1, // one attribute (i.e. IP addr)
1, // max? there is only one attr, come on
&cTotal,
nModifyMagic,
cPrefix,
pszPrefix);
if (hr != S_OK)
goto MyExit;
// Fill in modify list
//
MyAssert (ppMod != NULL);
LDAPMod *pMod;
pMod = ppMod[cPrefix];
MyAssert (pMod != NULL);
pMod->mod_type = pszAttrName;
// Put in ip address
//
pMod->mod_values = (TCHAR **) (pMod + 1);
*(pMod->mod_values) = pszAttrValue;
// Get the session object
//
hr = g_pSessionContainer->GetSession (ppSession, pServerInfo, FALSE);
if (hr != S_OK)
goto MyExit;
MyAssert (*ppSession != NULL);
// Get the ldap session
//
ld = (*ppSession)->GetLd ();
MyAssert (ld != NULL);
// Send the data over the wire
//
*puMsgID = ldap_modify (ld, pszDN, ppMod);
if (*puMsgID == -1)
{
hr = ::LdapError2Hresult (ld->ld_errno);
(*ppSession)->Disconnect ();
goto MyExit;
}
// Success
//
hr = S_OK;
MyExit:
MemFree (ppMod);
return hr;
}
HRESULT
IlsUpdateIPAddress (
SERVER_INFO *pServerInfo,
TCHAR *pszDN,
TCHAR *pszIPAddrName,
TCHAR *pszIPAddrValue,
LONG nModifyMagic,
ULONG cPrefix,
TCHAR *pszPrefix )
{
SP_CSession *pSession = NULL;
LDAP *ld;
ULONG uMsgID;
// Update the ip address attribute on the server
//
HRESULT hr = IlsUpdateOneAttr ( pServerInfo,
pszDN,
pszIPAddrName,
pszIPAddrValue,
nModifyMagic,
cPrefix,
pszPrefix,
&pSession,
&uMsgID);
if (hr != S_OK)
return hr;
// Get the ldap session
//
MyAssert (pSession != NULL);
ld = pSession->GetLd ();
MyAssert (ld != NULL);
// Let's wait for the result
//
LDAP_TIMEVAL TimeVal;
TimeVal.tv_usec = 0;
TimeVal.tv_sec = pSession->GetServerTimeoutInSecond ();
// We don't care the result.
// Should it fails, nothing we can do.
// We can try it again in next keep alive time.
//
LDAPMessage *pLdapMsg;
pLdapMsg = NULL;
ldap_result (ld, uMsgID, LDAP_MSG_ALL, &TimeVal, &pLdapMsg);
// Free message
//
if (pLdapMsg != NULL)
ldap_msgfree (pLdapMsg);
// Free up the session
//
if (pSession != NULL)
pSession->Disconnect ();
return S_OK;
}
HRESULT
IlsSendRefreshMsg (
SERVER_INFO *pServerInfo,
TCHAR *pszBaseDN,
TCHAR *pszTTL,
TCHAR *pszRefreshFilter,
ULONG *puTTL )
{
MyAssert (pServerInfo != NULL);
MyAssert (MyIsGoodString (pszBaseDN));
MyAssert (MyIsGoodString (pszTTL));
MyAssert (MyIsGoodString (pszRefreshFilter));
MyAssert (puTTL != NULL);
// Let's check to see if we need to use Ping...
//
if (g_pPing != NULL && g_pPing->IsAutodialEnabled ())
{
LPTSTR pszServerName = My_strdup(pServerInfo->pszServerName);
if (NULL == pszServerName)
{
return E_OUTOFMEMORY;
}
LPTSTR pszSeparator = My_strchr(pszServerName, _T(':'));
if (NULL != pszSeparator)
{
*pszSeparator = _T('\0');
}
DWORD dwIPAddr = inet_addr (pszServerName);
MemFree(pszServerName);
if (dwIPAddr != INADDR_NONE)
{
if (g_pPing->Ping (dwIPAddr, 10 * 1000, 9) == S_FALSE)
{
MyDebugMsg ((ZONE_KA, "KA: ping failed, network down\r\n"));
// The "ping" operation failed, but other operations failed
//
return ILS_E_NETWORK_DOWN;
}
}
}
// Get the connection object
//
SP_CSession *pSession = NULL;
HRESULT hr = g_pSessionContainer->GetSession (&pSession, pServerInfo, FALSE);
if (hr != S_OK)
{
MyDebugMsg ((ZONE_KA, "KA: network down, hr=0x%lX\r\n", hr));
// Report error
//
return ILS_E_NETWORK_DOWN;
}
MyAssert (pSession != NULL);
// Get the ldap session
//
LDAP *ld = pSession->GetLd ();
MyAssert (ld != NULL);
// Set attributes to return
//
TCHAR *apszAttrNames[2];
apszAttrNames[0] = pszTTL;
apszAttrNames[1] = 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,
pszBaseDN, // base DN
LDAP_SCOPE_BASE, // scope
pszRefreshFilter, // filter
&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 = pSession->GetServerTimeoutInSecond ();
// Wait and get the result back
//
LDAPMessage *pLdapMsg = NULL;
INT ResultType = ::ldap_result (ld, uMsgID, LDAP_MSG_ALL, &TimeVal, &pLdapMsg);
if (ResultType == LDAP_RES_SEARCH_ENTRY ||
ResultType == LDAP_RES_SEARCH_RESULT)
{
if (pLdapMsg != NULL)
{
switch (pLdapMsg->lm_returncode)
{
case LDAP_NO_SUCH_OBJECT:
MyDebugMsg ((ZONE_KA, "KA: no such object!\r\n"));
// Report error
//
hr = ILS_E_NEED_RELOGON;
break;
case LDAP_SUCCESS:
// Get the new refresh period
//
hr = ::IlsParseRefreshPeriod (ld, pLdapMsg, pszTTL, puTTL);
break;
default:
MyDebugMsg ((ZONE_KA, "KA: unknown lm_returncode=%ld\r\n", pLdapMsg->lm_returncode));
MyAssert (FALSE);
hr = ::LdapError2Hresult (ld->ld_errno);
break;
}
// Free this message
//
ldap_msgfree (pLdapMsg);
} // if (pLdapMsg != NULL)
else
{
hr = ILS_E_FAIL;
}
} // not timeout
else
{
// Timeout
//
hr = ILS_E_TIMEOUT;
}
// Free up the session
//
pSession->Disconnect ();
return hr;
}
HRESULT
IlsFillDefStdAttrsModArr (
LDAPMod ***pppMod,
DWORD dwFlags,
ULONG cMaxAttrs,
ULONG *pcTotal, // in/out parameter!!!
LONG IsbuModOp,
ULONG cPrefix,
TCHAR *pszPrefix )
{
MyAssert (pppMod != NULL);
MyAssert (pcTotal != NULL);
MyAssert ( (cPrefix == 0 && pszPrefix == NULL) ||
(cPrefix != 0 && pszPrefix != NULL));
// Figure out the num of attributes
//
ULONG cAttrs = 0;
for (ULONG i = 0; i < cMaxAttrs; i++)
{
if (dwFlags & 0x01)
cAttrs++;
dwFlags >>= 1;
}
// Allocate modify list
//
ULONG cTotal = *pcTotal + cPrefix + cAttrs;
ULONG cbMod = IlsCalcModifyListSize (cTotal);
*pppMod = (LDAPMod **) MemAlloc (cbMod);
if (*pppMod == NULL)
return ILS_E_MEMORY;
// Fill in the modify list
//
LDAPMod *pMod;
for (i = 0; i < cTotal; i++)
{
pMod = IlsGetModifyListMod (pppMod, cTotal, i);
(*pppMod)[i] = pMod;
pMod->mod_values = (TCHAR **) (pMod + 1);
if (i < cPrefix)
{
pMod->mod_op = LDAP_MOD_REPLACE;
pMod->mod_type = pszPrefix;
pszPrefix += lstrlen (pszPrefix) + 1;
*(pMod->mod_values) = pszPrefix;
pszPrefix += lstrlen (pszPrefix) + 1;
}
}
// Fix up the first and the last ones
//
IlsFixUpModOp ((*pppMod)[0], LDAP_MOD_REPLACE, IsbuModOp);
(*pppMod)[cTotal] = NULL;
// Return the total number of entries
//
*pcTotal = cTotal;
return S_OK;
}
const TCHAR c_szAnyAttrPrefix[] = TEXT ("ILSA");
#define SIZE_ANY_ATTR_PREFIX (sizeof (c_szAnyAttrPrefix) / sizeof (TCHAR))
const TCHAR *
UlsLdap_GetExtAttrNamePrefix ( VOID )
{
return &c_szAnyAttrPrefix[0];
}
const TCHAR *
IlsSkipAnyAttrNamePrefix ( const TCHAR *pszAttrName )
{
MyAssert (pszAttrName != NULL);
const TCHAR *psz = IlsIsAnyAttrName (pszAttrName);
if (psz == NULL)
{
MyAssert (FALSE);
psz = pszAttrName;
}
return psz;
}
const TCHAR *
IlsIsAnyAttrName ( const TCHAR *pszAttrName )
{
BOOL fRet = FALSE;
TCHAR *psz = (TCHAR *) pszAttrName;
if (pszAttrName != NULL)
{
if (lstrlen (pszAttrName) > SIZE_ANY_ATTR_PREFIX)
{
TCHAR c = pszAttrName[SIZE_ANY_ATTR_PREFIX-1];
psz[SIZE_ANY_ATTR_PREFIX-1] = TEXT ('\0');
fRet = (My_lstrcmpi (pszAttrName, &c_szAnyAttrPrefix[0]) == 0);
psz[SIZE_ANY_ATTR_PREFIX-1] = c;
}
}
return (fRet ? &pszAttrName[SIZE_ANY_ATTR_PREFIX-1] : NULL);
}
TCHAR *
IlsPrefixNameValueArray (
BOOL fPair,
ULONG cAttrs,
const TCHAR *pszAttrs )
{
if (cAttrs == 0 || pszAttrs == NULL)
{
MyAssert (FALSE);
return NULL;
}
// compute the total size required
ULONG cbTotalSize = 0;
ULONG cbThisSize;
TCHAR *pszSrc = (TCHAR *) pszAttrs;
for (ULONG i = 0; i < cAttrs; i++)
{
// get name size
cbThisSize = lstrlen (pszSrc) + 1;
pszSrc += lstrlen (pszSrc) + 1;
// get value size as needed
if (fPair)
{
cbThisSize += lstrlen (pszSrc) + 1;
pszSrc += lstrlen (pszSrc) + 1;
}
// adjust the size
cbThisSize += SIZE_ANY_ATTR_PREFIX;
cbThisSize *= sizeof (TCHAR);
// accumulate it
cbTotalSize += cbThisSize;
}
// allocate the new buffer
TCHAR *pszPrefixAttrs = (TCHAR *) MemAlloc (cbTotalSize);
if (pszPrefixAttrs == NULL)
return NULL;
// copy the strings over to the new buffer
pszSrc = (TCHAR *) pszAttrs;
TCHAR *pszDst = pszPrefixAttrs;
for (i = 0; i < cAttrs; i++)
{
// copy prefix
lstrcpy (pszDst, &c_szAnyAttrPrefix[0]);
pszDst += lstrlen (pszDst); // no plus 1
// copy name
lstrcpy (pszDst, pszSrc);
pszDst += lstrlen (pszDst) + 1;
pszSrc += lstrlen (pszSrc) + 1;
// copy value as needed
if (fPair)
{
lstrcpy (pszDst, pszSrc);
pszDst += lstrlen (pszDst) + 1;
pszSrc += lstrlen (pszSrc) + 1;
}
}
return pszPrefixAttrs;
}
TCHAR *
IlsBuildDN (
TCHAR *pszBaseDN,
TCHAR *pszC,
TCHAR *pszO,
TCHAR *pszCN,
TCHAR *pszObjectClass )
{
MyAssert (MyIsGoodString (pszCN));
MyAssert (MyIsGoodString (pszObjectClass));
static TCHAR s_szC[] = TEXT ("c=");
static TCHAR s_szO[] = TEXT ("o=");
static TCHAR s_szCN[] = TEXT ("cn=");
static TCHAR s_szObjectClass[] = TEXT ("objectClass=");
static TCHAR s_szDelimiter[] = TEXT (", ");
enum { C_LENGTH = 2 };
enum { O_LENGTH = 2 };
enum { CN_LENGTH = 3 };
enum { OBJECTCLASS_LENGTH = 12 };
enum { DELIMITER_LENGTH = 2 };
ULONG cchDN = 1;
BOOL fInBaseDN;
ASSERT(MyIsGoodString(pszC));
cchDN += lstrlen (pszC) + DELIMITER_LENGTH + C_LENGTH;
if (MyIsGoodString (pszBaseDN))
{
fInBaseDN = TRUE;
cchDN += lstrlen (pszBaseDN) + DELIMITER_LENGTH;
}
else
{
fInBaseDN = FALSE;
if (MyIsGoodString (pszO))
cchDN += lstrlen (pszO) + DELIMITER_LENGTH + O_LENGTH;
}
if (MyIsGoodString (pszCN))
cchDN += lstrlen (pszCN) + CN_LENGTH;
if (MyIsGoodString (pszObjectClass))
cchDN += lstrlen (pszObjectClass) + DELIMITER_LENGTH + OBJECTCLASS_LENGTH;
TCHAR *pszDN = (TCHAR *) MemAlloc (cchDN * sizeof (TCHAR));
if (pszDN != NULL)
{
TCHAR *psz = pszDN;
psz[0] = TEXT ('\0');
if (MyIsGoodString (pszC))
{
lstrcpy (psz, &s_szC[0]);
psz += lstrlen (psz);
lstrcpy (psz, pszC);
psz += lstrlen (psz);
}
if (fInBaseDN)
{
if (psz != pszDN)
{
lstrcpy (psz, &s_szDelimiter[0]);
psz += lstrlen (psz);
}
lstrcpy (psz, pszBaseDN);
psz += lstrlen (psz);
}
else
{
if (MyIsGoodString (pszO))
{
if (psz != pszDN)
{
lstrcpy (psz, &s_szDelimiter[0]);
psz += lstrlen (psz);
}
lstrcpy (psz, &s_szO[0]);
psz += lstrlen (psz);
lstrcpy (psz, pszO);
psz += lstrlen (psz);
}
}
if (MyIsGoodString (pszCN))
{
if (psz != pszDN)
{
lstrcpy (psz, &s_szDelimiter[0]);
psz += lstrlen (psz);
}
lstrcpy (psz, &s_szCN[0]);
psz += lstrlen (psz);
lstrcpy (psz, pszCN);
psz += lstrlen (psz);
}
if (MyIsGoodString (pszObjectClass))
{
if (psz != pszDN)
{
lstrcpy (psz, &s_szDelimiter[0]);
psz += lstrlen (psz);
}
lstrcpy (psz, &s_szObjectClass[0]);
psz += lstrlen (psz);
lstrcpy (psz, pszObjectClass);
psz += lstrlen (psz);
}
MyAssert (psz == pszDN + cchDN - 1);
}
return pszDN;
}
HRESULT
IlsCreateAnyAttrsPrefix ( ANY_ATTRS *pAnyAttrs )
{
if (pAnyAttrs->cAttrsToAdd != 0)
{
MyAssert (pAnyAttrs->pszAttrsToAdd != NULL);
pAnyAttrs->pszAttrsToAdd = IlsPrefixNameValueArray (
TRUE,
pAnyAttrs->cAttrsToAdd,
(const TCHAR *) pAnyAttrs->pszAttrsToAdd);
if (pAnyAttrs->pszAttrsToAdd == NULL)
return ILS_E_MEMORY;
}
if (pAnyAttrs->cAttrsToModify != 0)
{
MyAssert (pAnyAttrs->pszAttrsToModify != NULL);
pAnyAttrs->pszAttrsToModify = IlsPrefixNameValueArray (
TRUE,
pAnyAttrs->cAttrsToModify,
(const TCHAR *) pAnyAttrs->pszAttrsToModify);
if (pAnyAttrs->pszAttrsToModify == NULL)
{
MemFree (pAnyAttrs->pszAttrsToAdd);
pAnyAttrs->pszAttrsToAdd = NULL;
return ILS_E_MEMORY;
}
}
if (pAnyAttrs->cAttrsToRemove != 0)
{
MyAssert (pAnyAttrs->pszAttrsToRemove != NULL);
pAnyAttrs->pszAttrsToRemove = IlsPrefixNameValueArray (
FALSE,
pAnyAttrs->cAttrsToRemove,
(const TCHAR *) pAnyAttrs->pszAttrsToRemove);
if (pAnyAttrs->pszAttrsToRemove == NULL)
{
MemFree (pAnyAttrs->pszAttrsToAdd);
MemFree (pAnyAttrs->pszAttrsToModify);
pAnyAttrs->pszAttrsToAdd = NULL;
pAnyAttrs->pszAttrsToModify = NULL;
return ILS_E_MEMORY;
}
}
return S_OK;
}
VOID
IlsReleaseAnyAttrsPrefix ( ANY_ATTRS *pAnyAttrs )
{
MemFree (pAnyAttrs->pszAttrsToAdd);
MemFree (pAnyAttrs->pszAttrsToModify);
MemFree (pAnyAttrs->pszAttrsToRemove);
ZeroMemory (pAnyAttrs, sizeof (*pAnyAttrs));
}
TCHAR **my_ldap_get_values ( LDAP *ld, LDAPMessage *pEntry, TCHAR *pszRetAttrName )
{
MyAssert (ld != NULL);
MyAssert (pEntry != NULL);
MyAssert (pszRetAttrName != NULL);
// Examine the first attribute
//
struct berelement *pContext = NULL;
TCHAR *pszAttrName = ldap_first_attribute (ld, pEntry, &pContext);
if (My_lstrcmpi (pszAttrName, pszRetAttrName) != 0)
{
// Examine the other attributes
//
while ((pszAttrName = ldap_next_attribute (ld, pEntry, pContext))
!= NULL)
{
if (My_lstrcmpi (pszAttrName, pszRetAttrName) == 0)
break;
}
}
// Get the attribute value if needed
//
TCHAR **ppszAttrValue = NULL;
if (pszAttrName != NULL)
ppszAttrValue = ldap_get_values (ld, pEntry, pszAttrName);
return ppszAttrValue;
}
ULONG my_ldap_count_1st_entry_attributes ( LDAP *ld, LDAPMessage *pLdapMsg )
{
MyAssert (ld != NULL);
MyAssert (pLdapMsg != NULL);
ULONG cAttrs = 0;
// there should be only an entry
ULONG cEntries = ldap_count_entries (ld, pLdapMsg);
if (cEntries > 0)
{
// there should be only one entry
MyAssert (cEntries == 1);
TCHAR *pszAttrName;
// get this entry
LDAPMessage *pEntry = ldap_first_entry (ld, pLdapMsg);
if (pEntry == NULL)
{
MyAssert (FALSE);
return cAttrs;
}
// examine the first attribute
struct berelement *pContext = NULL;
pszAttrName = ldap_first_attribute (ld, pEntry, &pContext);
if (pszAttrName == NULL)
{
MyAssert (FALSE);
return 0;
}
cAttrs = 1;
TCHAR **ppszAttrVal;
ppszAttrVal = ldap_get_values (ld, pEntry, pszAttrName);
if (ppszAttrVal != NULL)
ldap_value_free (ppszAttrVal);
// step through the others
while ((pszAttrName = ldap_next_attribute (ld, pEntry, pContext)) != NULL)
{
cAttrs++;
ppszAttrVal = ldap_get_values (ld, pEntry, pszAttrName);
if (ppszAttrVal != NULL)
ldap_value_free (ppszAttrVal);
}
} // if cEntries > 0
return cAttrs;
}