WindowsXP-SP1/enduser/netmeeting/ulsldap/spanyatt.cpp

578 lines
12 KiB
C++

/* ----------------------------------------------------------------------
Module: ULS.DLL (Service Provider)
File: spanyatt.cpp
Content: This file contains the arbitrary-attribute object.
History:
10/15/96 Chu, Lon-Chan [lonchanc]
Created.
Copyright (c) Microsoft Corporation 1996-1997
---------------------------------------------------------------------- */
#include "ulsp.h"
#include "spinc.h"
/* ---------- public methods ----------- */
UlsLdap_CAnyAttrs::UlsLdap_CAnyAttrs ( VOID )
{
m_cAttrs = 0;
m_AttrList = NULL;
}
UlsLdap_CAnyAttrs::~UlsLdap_CAnyAttrs ( VOID )
{
FreeAttrList (m_AttrList);
}
/* ---------- protected methods ----------- */
HRESULT UlsLdap_CAnyAttrs::SetAnyAttrs (
ULONG *puRespID,
ULONG *puMsgID,
ULONG uNotifyMsg,
ULONG cAttrs,
TCHAR *pszAttrs,
ULONG cPrefix,
TCHAR *pszPrefix,
LONG ModOp,
SERVER_INFO *pServerInfo,
TCHAR *pszDN )
{
MyAssert (puRespID != NULL || puMsgID != NULL);
MyAssert (cAttrs != 0);
MyAssert (pszAttrs != NULL);
MyAssert (cPrefix != 0);
MyAssert (pszPrefix != NULL);
MyAssert (pServerInfo != NULL);
MyAssert (pszDN != NULL);
MyAssert (ModOp == LDAP_MOD_REPLACE || ModOp == LDAP_MOD_ADD);
// create a prefix for each attr name in the following pair
pszAttrs = PrefixNameValueArray (TRUE, cAttrs, pszAttrs);
if (pszAttrs == NULL)
return ULS_E_MEMORY;
// build modify array for ldap_modify()
LDAPMod **ppMod = NULL;
HRESULT hr = SetAttrsAux (cAttrs, pszAttrs, cPrefix, pszPrefix, ModOp, &ppMod);
if (hr != S_OK)
{
MemFree (pszAttrs);
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, pServerInfo);
if (hr != S_OK)
{
MemFree (pszAttrs);
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_modify (ld, pszDN, ppMod);
MemFree (pszAttrs);
MemFree (ppMod);
if (uMsgID == -1)
{
hr = ::LdapError2Hresult (ld->ld_errno);
pSession->Disconnect ();
return hr;
}
// if the caller does not ask for notify id
// then do not queue a pending info
if (puRespID != NULL)
{
PENDING_INFO PendingInfo;
::FillDefPendingInfo (&PendingInfo, ld, uMsgID, INVALID_MSG_ID);
PendingInfo.uLdapResType = LDAP_RES_MODIFY;
PendingInfo.uNotifyMsg = uNotifyMsg;
// queue it
hr = g_pPendingQueue->EnterRequest (pSession, &PendingInfo);
if (hr != S_OK)
{
ldap_abandon (ld, uMsgID);
pSession->Disconnect ();
MyAssert (FALSE);
}
*puRespID = PendingInfo.uRespID;
}
if (puMsgID)
*puMsgID = uMsgID;
return hr;
}
HRESULT UlsLdap_CAnyAttrs::RemoveAllAnyAttrs (
ULONG *puMsgID,
ULONG cPrefix,
TCHAR *pszPrefix,
SERVER_INFO *pServerInfo,
TCHAR *pszDN )
{
ULONG cbAttrs = 0;
ULONG cAttrs = 0;
for (ANY_ATTR *p = m_AttrList; p != NULL; p = p->next)
{
cAttrs++;
if (p->pszAttrName != NULL)
cbAttrs += (lstrlen (p->pszAttrName) + 1) * sizeof (TCHAR);
}
MyAssert (cAttrs == m_cAttrs);
TCHAR *pszAttrs = (TCHAR *) MemAlloc (cbAttrs);
if (pszAttrs == NULL)
return ULS_E_MEMORY;
TCHAR *psz = pszAttrs;
for (p = m_AttrList; p != NULL; p = p->next)
{
if (p->pszAttrName != NULL)
{
lstrcpy (psz, p->pszAttrName);
psz += lstrlen (psz) + 1;
}
}
HRESULT hr = RemoveAnyAttrsEx ( NULL,
puMsgID,
0,
cAttrs,
pszAttrs,
cPrefix,
pszPrefix,
pServerInfo,
pszDN);
MemFree (pszAttrs);
return hr;
}
HRESULT UlsLdap_CAnyAttrs::RemoveAnyAttrs (
ULONG *puRespID,
ULONG *puMsgID,
ULONG uNotifyMsg,
ULONG cAttrs,
TCHAR *pszAttrs,
ULONG cPrefix,
TCHAR *pszPrefix,
SERVER_INFO *pServerInfo,
TCHAR *pszDN)
{
MyAssert (puRespID != NULL || puMsgID != NULL);
MyAssert (cAttrs != 0);
MyAssert (pszAttrs != NULL);
MyAssert (cPrefix != 0);
MyAssert (pszPrefix != NULL);
MyAssert (pServerInfo != NULL);
MyAssert (pszDN != NULL);
pszAttrs = PrefixNameValueArray (FALSE, cAttrs, pszAttrs);
if (pszAttrs == NULL)
return ULS_E_MEMORY;
HRESULT hr = RemoveAnyAttrsEx ( puRespID,
puMsgID,
uNotifyMsg,
cAttrs,
pszAttrs,
cPrefix,
pszPrefix,
pServerInfo,
pszDN);
MemFree (pszAttrs);
return hr;
}
HRESULT UlsLdap_CAnyAttrs::RemoveAnyAttrsEx (
ULONG *puRespID,
ULONG *puMsgID,
ULONG uNotifyMsg,
ULONG cAttrs,
TCHAR *pszAttrs,
ULONG cPrefix,
TCHAR *pszPrefix,
SERVER_INFO *pServerInfo,
TCHAR *pszDN)
{
MyAssert (puRespID != NULL || puMsgID != NULL);
MyAssert (cAttrs != 0);
MyAssert (pszAttrs != NULL);
MyAssert (cPrefix != 0);
MyAssert (pszPrefix != NULL);
MyAssert (pServerInfo != NULL);
MyAssert (pszDN != NULL);
// build modify array for ldap_modify()
LDAPMod **ppMod = NULL;
HRESULT hr = RemoveAttrsAux (cAttrs, pszAttrs, cPrefix, pszPrefix, &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, pServerInfo);
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_modify (ld, pszDN, ppMod);
MemFree (ppMod);
if (uMsgID == -1)
{
hr = ::LdapError2Hresult (ld->ld_errno);
pSession->Disconnect ();
return hr;
}
// if the caller does not ask for notify id
// then do not queue a pending info
if (puRespID != NULL)
{
PENDING_INFO PendingInfo;
::FillDefPendingInfo (&PendingInfo, ld, uMsgID, INVALID_MSG_ID);
PendingInfo.uLdapResType = LDAP_RES_MODIFY;
PendingInfo.uNotifyMsg = uNotifyMsg;
hr = g_pPendingQueue->EnterRequest (pSession, &PendingInfo);
if (hr != S_OK)
{
ldap_abandon (ld, uMsgID);
pSession->Disconnect ();
MyAssert (FALSE);
}
*puRespID = PendingInfo.uRespID;
}
else
{
if (puMsgID != NULL)
*puMsgID = uMsgID;
}
return hr;
}
/* ---------- private methods ----------- */
HRESULT UlsLdap_CAnyAttrs::SetAttrsAux (
ULONG cAttrs,
TCHAR *pszAttrs,
ULONG cPrefix,
TCHAR *pszPrefix,
LONG ModOp,
LDAPMod ***pppMod )
{
MyAssert (cAttrs != 0);
MyAssert (pszAttrs != NULL);
MyAssert (cPrefix != 0);
MyAssert (pszPrefix != NULL);
MyAssert (ModOp == LDAP_MOD_REPLACE || ModOp == LDAP_MOD_ADD);
MyAssert (pppMod != NULL);
// create modify list
ULONG cTotal = cPrefix + cAttrs;
ULONG cbMod = ::IlsCalcModifyListSize (cTotal);
*pppMod = (LDAPMod **) MemAlloc (cbMod);
if (*pppMod == NULL)
{
return ULS_E_MEMORY;
}
LDAPMod *pMod;
for (ULONG 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;
}
else
{
pMod->mod_op = ModOp;
if (LocateAttr (pszAttrs) == NULL)
{
pMod->mod_op = LDAP_MOD_ADD;
m_cAttrs++;
}
if (pMod->mod_op == LDAP_MOD_ADD)
{
ULONG cbAttrSize = sizeof (ANY_ATTR) + sizeof (TCHAR) *
(lstrlen (pszAttrs) + 1);
ANY_ATTR *pNew = (ANY_ATTR *) MemAlloc (cbAttrSize);
if (pNew == NULL)
{
return ULS_E_MEMORY;
}
// fill in attr name
pNew->pszAttrName = (TCHAR *) (pNew + 1);
lstrcpy (pNew->pszAttrName, pszAttrs);
// link to the list
pNew->prev = NULL;
pNew->next = m_AttrList;
m_AttrList = pNew;
}
pMod->mod_type = pszAttrs;
pszAttrs += lstrlen (pszAttrs) + 1;
*(pMod->mod_values) = pszAttrs;
pszAttrs += lstrlen (pszAttrs) + 1;
}
}
(*pppMod)[cTotal] = NULL;
::IlsFixUpModOp ((*pppMod)[0], ModOp, ISBU_MODOP_MODIFY_APP);
return S_OK;
}
HRESULT UlsLdap_CAnyAttrs::RemoveAttrsAux (
ULONG cAttrs,
TCHAR *pszAttrs,
ULONG cPrefix,
TCHAR *pszPrefix,
LDAPMod ***pppMod )
{
MyAssert (cAttrs != 0);
MyAssert (pszAttrs != NULL);
MyAssert (cPrefix != 0);
MyAssert (pszPrefix != NULL);
MyAssert (pppMod != NULL);
// create modify list
ULONG cTotal = cPrefix + cAttrs;
ULONG cbMod = ::IlsCalcModifyListSize (cTotal);
*pppMod = (LDAPMod **) MemAlloc (cbMod);
if (*pppMod == NULL)
{
return ULS_E_MEMORY;
}
LDAPMod *pMod;
for (ULONG i = 0; i < cTotal; i++)
{
pMod = ::IlsGetModifyListMod (pppMod, cTotal, i);
(*pppMod)[i] = pMod;
if (i < cPrefix)
{
pMod->mod_op = LDAP_MOD_REPLACE;
pMod->mod_type = pszPrefix;
pszPrefix += lstrlen (pszPrefix) + 1;
pMod->mod_values = (TCHAR **) (pMod + 1);
*(pMod->mod_values) = pszPrefix;
pszPrefix += lstrlen (pszPrefix) + 1;
}
else
{
pMod->mod_op = LDAP_MOD_DELETE;
RemoveAttrFromList (pszAttrs);
pMod->mod_type = pszAttrs;
pszAttrs += lstrlen (pszAttrs) + 1;
}
}
(*pppMod)[cTotal] = NULL;
::IlsFixUpModOp ((*pppMod)[0], LDAP_MOD_REPLACE, ISBU_MODOP_MODIFY_APP);
return S_OK;
}
VOID UlsLdap_CAnyAttrs::RemoveAttrFromList ( TCHAR *pszAttrName )
{
ANY_ATTR *pOld = LocateAttr (pszAttrName);
if (pOld != NULL)
{
// remove it
if (pOld->prev != NULL)
{
pOld->prev->next = pOld->next;
}
else
{
m_AttrList = pOld->next;
}
if (pOld->next != NULL)
{
pOld->next->prev = pOld->prev;
}
MyAssert (m_cAttrs != 0);
m_cAttrs--;
}
}
VOID UlsLdap_CAnyAttrs::FreeAttrList ( ANY_ATTR *AttrList )
{
ANY_ATTR *pCurr, *pNext;
for (pCurr = AttrList; pCurr != NULL; pCurr = pNext)
{
pNext = pCurr->next;
MemFree (pCurr);
}
}
ANY_ATTR *UlsLdap_CAnyAttrs::LocateAttr ( TCHAR *pszAttrName )
{
ANY_ATTR *pAttr;
for (pAttr = m_AttrList; pAttr != NULL; pAttr = pAttr->next)
{
if (! My_lstrcmpi (pszAttrName, pAttr->pszAttrName))
{
break;
}
}
return pAttr;
}
// const TCHAR c_szAnyAttrPrefix[] = TEXT ("ulsaan_");
const TCHAR c_szAnyAttrPrefix[] = TEXT ("ILSA");
#define SIZE_ANY_ATTR_PREFIX (sizeof (c_szAnyAttrPrefix) / sizeof (TCHAR))
const TCHAR *SkipAnyAttrNamePrefix ( const TCHAR *pszAttrName )
{
MyAssert (pszAttrName != NULL);
const TCHAR *psz = IsAnyAttrName (pszAttrName);
if (psz == NULL)
{
MyAssert (FALSE);
psz = pszAttrName;
}
return psz;
}
const TCHAR *IsAnyAttrName ( 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 *PrefixNameValueArray ( 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;
}