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