DWORD VmDirSchemaAttrIdMapGetAttrId( PVDIR_SCHEMA_ATTR_ID_MAP pAttrIdMap, PSTR pszAttrName, USHORT* pusAttrId ) { DWORD dwError = 0; uintptr_t pAttrId = 0; if (!pAttrIdMap || IsNullOrEmptyString(pszAttrName)) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } dwError = LwRtlHashMapFindKey(pAttrIdMap->pStoredIds, (PVOID*)&pAttrId, pszAttrName); if (dwError) { dwError = LwRtlHashMapFindKey(pAttrIdMap->pNewIds, (PVOID*)&pAttrId, pszAttrName); } BAIL_ON_VMDIR_ERROR(dwError); if (pusAttrId) { *pusAttrId = (USHORT)pAttrId; } error: return dwError; }
DWORD VmDirUTDVectorCacheLookup( PVMDIR_UTDVECTOR_CACHE pUTDVector, PCSTR pszInvocationId, USN* pUsn ) { DWORD dwError = 0; BOOLEAN bInLock = FALSE; uintptr_t usn = 0; PVMDIR_UTDVECTOR_CACHE pCache = pUTDVector; if (IsNullOrEmptyString(pszInvocationId) || !pUsn || !pUTDVector) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER); } VMDIR_RWLOCK_READLOCK(bInLock, pCache->pUtdVectorLock, 0); dwError = LwRtlHashMapFindKey(pCache->pUtdVectorMap, (PVOID*)&usn, pszInvocationId); BAIL_ON_VMDIR_ERROR(dwError); *pUsn = (USN)usn; cleanup: VMDIR_RWLOCK_UNLOCK(bInLock, pCache->pUtdVectorLock); return dwError; error: VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d)", dwError); goto cleanup; }
NTSTATUS RdrResolveToDomain( PCWSTR pwszHostname, PWSTR* ppwszDomain ) { NTSTATUS status = STATUS_SUCCESS; BOOLEAN bLocked = FALSE; PWSTR pwszDomain = NULL; LWIO_LOCK_MUTEX(bLocked, &gRdrRuntime.Lock); if (!gRdrRuntime.pDomainHints) { status = STATUS_NOT_FOUND; } else { status = LwRtlHashMapFindKey( gRdrRuntime.pDomainHints, OUT_PPVOID(&pwszDomain), pwszHostname); } BAIL_ON_NT_STATUS(status); status = LwRtlWC16StringDuplicate(ppwszDomain, pwszDomain); BAIL_ON_NT_STATUS(status); error: LWIO_UNLOCK_MUTEX(bLocked, &gRdrRuntime.Lock); return status; }
DWORD VmDirIndexCfgAcquire( PCSTR pszAttrName, VDIR_INDEX_USAGE usage, PVDIR_INDEX_CFG* ppIndexCfg ) { DWORD dwError = 0; BOOLEAN bInLock = FALSE; PVDIR_INDEX_CFG pIndexCfg = NULL; PVMDIR_MUTEX pMutex = NULL; if (IsNullOrEmptyString(pszAttrName) || !ppIndexCfg) { dwError = VMDIR_ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } *ppIndexCfg = NULL; if (LwRtlHashMapFindKey( gVdirIndexGlobals.pIndexCfgMap, (PVOID*)&pIndexCfg, pszAttrName)) { goto cleanup; } pMutex = pIndexCfg->mutex; VMDIR_LOCK_MUTEX(bInLock, pMutex); if (pIndexCfg->status == VDIR_INDEXING_SCHEDULED) { goto cleanup; } else if (pIndexCfg->status == VDIR_INDEXING_IN_PROGRESS && usage == VDIR_INDEX_READ) { dwError = VMDIR_ERROR_UNWILLING_TO_PERFORM; } else if (pIndexCfg->status == VDIR_INDEXING_DISABLED || pIndexCfg->status == VDIR_INDEXING_DELETED) { goto cleanup; } BAIL_ON_VMDIR_ERROR(dwError); pIndexCfg->usRefCnt++; *ppIndexCfg = pIndexCfg; cleanup: VMDIR_UNLOCK_MUTEX(bInLock, pMutex); return dwError; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s failed, error (%d)", __FUNCTION__, dwError ); goto cleanup; }
BOOLEAN VmDirIndexExist( PCSTR pszAttrName ) { BOOLEAN bExist = TRUE; PLW_HASHMAP pCurMap = NULL; PLW_HASHMAP pUpdMap = NULL; PVDIR_INDEX_CFG pIndexCfg = NULL; pCurMap = gVdirIndexGlobals.pIndexCfgMap; pUpdMap = gVdirIndexGlobals.pIndexUpd ? gVdirIndexGlobals.pIndexUpd->pUpdIndexCfgMap : NULL; if (IsNullOrEmptyString(pszAttrName)) { bExist = FALSE; } else { if (pUpdMap) { LwRtlHashMapFindKey(pUpdMap, (PVOID*)&pIndexCfg, pszAttrName); } if (!pIndexCfg) { LwRtlHashMapFindKey(pCurMap, (PVOID*)&pIndexCfg, pszAttrName); } if (!pIndexCfg || pIndexCfg->status == VDIR_INDEXING_DISABLED || pIndexCfg->status == VDIR_INDEXING_DELETED) { bExist = FALSE; } } return bExist; }
BOOLEAN VmDirIndexIsDefault( PCSTR pszAttrName ) { BOOLEAN bIsDefault = FALSE; PVDIR_INDEX_CFG pIndexCfg = NULL; if (!IsNullOrEmptyString(pszAttrName) && LwRtlHashMapFindKey( gVdirIndexGlobals.pIndexCfgMap, (PVOID*)&pIndexCfg, pszAttrName) == 0) { bIsDefault = pIndexCfg->bDefaultIndex; } return bIsDefault; }
/* * should only be used during bootstrap * maybe add state check? */ DWORD VmDirIndexOpen( PVDIR_INDEX_CFG pIndexCfg ) { DWORD dwError = 0; BOOLEAN bInLock = FALSE; PVDIR_BACKEND_INTERFACE pBE = NULL; if (!pIndexCfg) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } VMDIR_LOCK_MUTEX(bInLock, gVdirIndexGlobals.mutex); if (LwRtlHashMapFindKey( gVdirIndexGlobals.pIndexCfgMap, NULL, pIndexCfg->pszAttrName) == 0) { dwError = ERROR_ALREADY_INITIALIZED; BAIL_ON_VMDIR_ERROR(dwError); } dwError = LwRtlHashMapInsert( gVdirIndexGlobals.pIndexCfgMap, pIndexCfg->pszAttrName, pIndexCfg, NULL); BAIL_ON_VMDIR_ERROR(dwError); pBE = VmDirBackendSelect(NULL); dwError = pBE->pfnBEIndexOpen(pIndexCfg); BAIL_ON_VMDIR_ERROR(dwError); cleanup: VMDIR_UNLOCK_MUTEX(bInLock, gVdirIndexGlobals.mutex); return dwError; error: goto cleanup; }
static DWORD _populateHashMapWithSuperlogEntries( PLW_HASHMAP pHashMap, PVMDIR_SUPERLOG_ENTRY_LDAPOPERATION_ARRAY pEntries, PVMDIR_SUPERLOG_TABLE_COLUMN_SET pCols ) { DWORD dwError = 0; PSTR pszKey = NULL; PVMDIR_SUPERLOG_TABLE_ROW pValue = NULL; unsigned int i; for (i = 0; i < pEntries->dwCount; i++) { dwError = _generateHashMapKeyString(&pEntries->entries[i], pCols, &pszKey); BAIL_ON_VMDIR_ERROR(dwError); dwError = LwRtlHashMapFindKey(pHashMap, (PVOID*)&pValue, pszKey); if (dwError == 0) { pValue->count += 1; pValue->totalTime += pEntries->entries[i].iEndTime - pEntries->entries[i].iStartTime; VMDIR_SAFE_FREE_MEMORY(pszKey); } else { dwError = _allocateSuperlogTableRow(&pEntries->entries[i], pCols, &pValue); BAIL_ON_VMDIR_ERROR(dwError); dwError = LwRtlHashMapInsert(pHashMap, pszKey, pValue, NULL); BAIL_ON_VMDIR_ERROR(dwError); } } cleanup: return dwError; error: goto cleanup; }
BOOLEAN VmDirConsumerRoleActive( VOID ) { BOOLEAN bInLock = FALSE; BOOLEAN bActiveReplCycle = FALSE; VMDIR_LOCK_MUTEX(bInLock, gVmdirServerGlobals.pReplDeadlockDetectionVector->pMutex); // if consumer role is active, then DD vector will definitely have bvServerObjName key if (LwRtlHashMapFindKey( gVmdirServerGlobals.pReplDeadlockDetectionVector->pEmptyPageSentMap, NULL, gVmdirServerGlobals.bvServerObjName.lberbv_val) == 0) { bActiveReplCycle = TRUE; } VMDIR_UNLOCK_MUTEX(bInLock, gVmdirServerGlobals.pReplDeadlockDetectionVector->pMutex); return bActiveReplCycle; }
DWORD VmDirIndexDeleteUniquenessScope( PVDIR_INDEX_UPD pIndexUpd, PCSTR pszAttrName, PCSTR* ppszUniqScopes ) { DWORD dwError = 0; DWORD i = 0; PLW_HASHMAP pCurCfgMap = NULL; PLW_HASHMAP pUpdCfgMap = NULL; PVDIR_INDEX_CFG pCurCfg = NULL; PVDIR_INDEX_CFG pUpdCfg = NULL; PVDIR_INDEX_CFG pNewCfg = NULL; if (!pIndexUpd || IsNullOrEmptyString(pszAttrName) || !ppszUniqScopes) { dwError = VMDIR_ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } pCurCfgMap = gVdirIndexGlobals.pIndexCfgMap; pUpdCfgMap = pIndexUpd->pUpdIndexCfgMap; (VOID)LwRtlHashMapFindKey(pCurCfgMap, (PVOID*)&pCurCfg, pszAttrName); (VOID)LwRtlHashMapFindKey(pUpdCfgMap, (PVOID*)&pUpdCfg, pszAttrName); if (pCurCfg && !pUpdCfg) { dwError = VmDirIndexCfgCopy(pCurCfg, &pUpdCfg); BAIL_ON_VMDIR_ERROR(dwError); pNewCfg = pUpdCfg; } if (!pUpdCfg || pUpdCfg->status == VDIR_INDEXING_DISABLED || pUpdCfg->status == VDIR_INDEXING_DELETED) { dwError = VMDIR_ERROR_NOT_FOUND; BAIL_ON_VMDIR_ERROR(dwError); } if (!pUpdCfg->bScopeEditable || pUpdCfg->status == VDIR_INDEXING_VALIDATING_SCOPES) { dwError = VMDIR_ERROR_UNWILLING_TO_PERFORM; BAIL_ON_VMDIR_ERROR(dwError); } for (i = 0; ppszUniqScopes[i]; i++) { dwError = VmDirIndexCfgDeleteUniqueScopeMod(pUpdCfg, ppszUniqScopes[i]); BAIL_ON_VMDIR_ERROR(dwError); } dwError = LwRtlHashMapInsert(pUpdCfgMap, pUpdCfg->pszAttrName, pUpdCfg, NULL); BAIL_ON_VMDIR_ERROR(dwError); cleanup: return dwError; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s failed, error (%d)", __FUNCTION__, dwError ); VmDirFreeIndexCfg(pNewCfg); goto cleanup; }
DWORD VmDirIndexSchedule( PVDIR_INDEX_UPD pIndexUpd, PCSTR pszAttrName, PCSTR pszAttrSyntaxOid ) { DWORD dwError = 0; PLW_HASHMAP pCurCfgMap = NULL; PLW_HASHMAP pUpdCfgMap = NULL; PVDIR_INDEX_CFG pCurCfg = NULL; PVDIR_INDEX_CFG pUpdCfg = NULL; PVDIR_INDEX_CFG pNewCfg = NULL; if (!pIndexUpd || IsNullOrEmptyString(pszAttrName)) { dwError = VMDIR_ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } pCurCfgMap = gVdirIndexGlobals.pIndexCfgMap; pUpdCfgMap = pIndexUpd->pUpdIndexCfgMap; (VOID)LwRtlHashMapFindKey(pCurCfgMap, (PVOID*)&pCurCfg, pszAttrName); (VOID)LwRtlHashMapFindKey(pUpdCfgMap, (PVOID*)&pUpdCfg, pszAttrName); if (pUpdCfg) { dwError = ERROR_ALREADY_EXISTS; BAIL_ON_VMDIR_ERROR(dwError); } if (pCurCfg) { if (pCurCfg->status == VDIR_INDEXING_DELETED) { dwError = VmDirIndexCfgCopy(pCurCfg, &pUpdCfg); BAIL_ON_VMDIR_ERROR(dwError); pNewCfg = pUpdCfg; pUpdCfg->status = VDIR_INDEXING_SCHEDULED; } else if (pCurCfg->status == VDIR_INDEXING_DISABLED) { dwError = VMDIR_ERROR_BUSY; BAIL_ON_VMDIR_ERROR(dwError); } else { dwError = ERROR_ALREADY_EXISTS; BAIL_ON_VMDIR_ERROR(dwError); } } else { dwError = VmDirIndexCfgCreate(pszAttrName, &pUpdCfg); BAIL_ON_VMDIR_ERROR(dwError); pNewCfg = pUpdCfg; pUpdCfg->bIsNumeric = VmDirSchemaSyntaxIsNumeric(pszAttrSyntaxOid); } dwError = LwRtlHashMapInsert(pUpdCfgMap, pUpdCfg->pszAttrName, pUpdCfg, NULL); BAIL_ON_VMDIR_ERROR(dwError); cleanup: return dwError; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s failed, error (%d)", __FUNCTION__, dwError ); VmDirFreeIndexCfg(pNewCfg); goto cleanup; }
DWORD VmDirDDVectorParseString( PSTR pszDeadlockDetectionVectorStr, PBOOLEAN pbCompleteReplCycle ) { PSTR pszLocalVectorStr = NULL; PDWORD pdwValue = NULL; DWORD dwError = 0; DWORD dwMinConsecutiveEmptyPage = INT_MAX; BOOLEAN bInLock = FALSE; LW_HASHMAP_ITER iter = LW_HASHMAP_ITER_INIT; LW_HASHMAP_PAIR pair = {NULL, NULL}; VMDIR_LOCK_MUTEX(bInLock, gVmdirServerGlobals.pReplDeadlockDetectionVector->pMutex); if (pszDeadlockDetectionVectorStr && pbCompleteReplCycle) { dwError = VmDirAllocateStringA(pszDeadlockDetectionVectorStr+VmDirStringLenA("vector:"), &pszLocalVectorStr); BAIL_ON_VMDIR_ERROR(dwError); // cache the counter value if (LwRtlHashMapFindKey( gVmdirServerGlobals.pReplDeadlockDetectionVector->pEmptyPageSentMap, (PVOID*)&pdwValue, gVmdirServerGlobals.bvServerObjName.lberbv_val) == 0) { dwMinConsecutiveEmptyPage = *pdwValue; dwMinConsecutiveEmptyPage++; VMDIR_LOG_INFO(LDAP_DEBUG_REPL, "consecutive empty pages received: %d", dwMinConsecutiveEmptyPage); } // clear and reconstruct the vector LwRtlHashMapClear( gVmdirServerGlobals.pReplDeadlockDetectionVector->pEmptyPageSentMap, VmDirSimpleHashMapPairFree, NULL); dwError = VmDirStrtoVector( pszLocalVectorStr, _VmDirDeadlockDetectionVectorStrToPair, gVmdirServerGlobals.pReplDeadlockDetectionVector->pEmptyPageSentMap); BAIL_ON_VMDIR_ERROR(dwError); // update the cached counter value dwError = _VmDirDDVectorUpdateDefaultsInLock(dwMinConsecutiveEmptyPage); BAIL_ON_VMDIR_ERROR(dwError); // check for replication cycle completion while (LwRtlHashMapIterate(gVmdirServerGlobals.pReplDeadlockDetectionVector->pEmptyPageSentMap, &iter, &pair)) { dwMinConsecutiveEmptyPage = VMDIR_MIN(dwMinConsecutiveEmptyPage, *(PDWORD)pair.pValue); } *pbCompleteReplCycle = (dwMinConsecutiveEmptyPage >= gVmdirGlobals.dwEmptyPageCnt); if (*pbCompleteReplCycle) { VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "%s: Break Empty Pages Received, vec: %s", __FUNCTION__, pszDeadlockDetectionVectorStr); } } else // if vector not present - non empty page - clear the vector contents { _VmDirDDVectorUpdateInLock(0); } cleanup: VMDIR_UNLOCK_MUTEX(bInLock, gVmdirServerGlobals.pReplDeadlockDetectionVector->pMutex); VMDIR_SAFE_FREE_MEMORY(pszLocalVectorStr); return dwError; error: VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d)", dwError); goto cleanup; }
DWORD VmDirDDVectorToString( PCSTR pszInvocationId, PSTR* ppszDeadlockDetectionVectorStr ) { PSTR pszDeadlockDetectionVectorStr = NULL; DWORD dwError = 0; PDWORD pdwValue = NULL; DWORD dwCacheEmptyPageCnt = 0; BOOLEAN bInLock = FALSE; BOOLEAN bRevertDefaultValue = FALSE; if (ppszDeadlockDetectionVectorStr == NULL) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER); } VMDIR_LOCK_MUTEX(bInLock, gVmdirServerGlobals.pReplDeadlockDetectionVector->pMutex); /* * Best effort if invocation id is NULL ignore. * Ping-pong state is handled by providing supplier's empty page * count as 'gVmdirGlobals.dwEmptyPageCnt' so that partner considers only his state */ if (gVmdirServerGlobals.pReplDeadlockDetectionVector->pszInvocationId && pszInvocationId && VmDirStringCompareA( pszInvocationId, gVmdirServerGlobals.pReplDeadlockDetectionVector->pszInvocationId, FALSE) == 0) { // will reach here only if key is present LwRtlHashMapFindKey( gVmdirServerGlobals.pReplDeadlockDetectionVector->pEmptyPageSentMap, (PVOID*)&pdwValue, gVmdirServerGlobals.bvServerObjName.lberbv_val); dwCacheEmptyPageCnt = *pdwValue; dwError = _VmDirDDVectorUpdateDefaultsInLock(gVmdirGlobals.dwEmptyPageCnt); BAIL_ON_VMDIR_ERROR(dwError); bRevertDefaultValue = TRUE; } dwError = VmDirVectorToStr( gVmdirServerGlobals.pReplDeadlockDetectionVector->pEmptyPageSentMap, _VmDirDeadlockDetectionVectorPairToStr, &pszDeadlockDetectionVectorStr); BAIL_ON_VMDIR_ERROR(dwError); *ppszDeadlockDetectionVectorStr = pszDeadlockDetectionVectorStr; pszDeadlockDetectionVectorStr = NULL; if (bRevertDefaultValue) { dwError = _VmDirDDVectorUpdateDefaultsInLock(dwCacheEmptyPageCnt); BAIL_ON_VMDIR_ERROR(dwError); } cleanup: VMDIR_UNLOCK_MUTEX(bInLock, gVmdirServerGlobals.pReplDeadlockDetectionVector->pMutex); return dwError; error: VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d)", dwError); goto cleanup; }
DWORD VmDirEntryIsAttrAllowed( PVDIR_ENTRY pEntry, PSTR pszAttrName, PBOOLEAN pbMust, PBOOLEAN pbMay ) { DWORD dwError = 0; DWORD i = 0; PVDIR_ATTRIBUTE pAttrOC = NULL; PVDIR_SCHEMA_OC_DESC pOCDesc = NULL; PLW_HASHMAP pAllMustAttrMap = NULL; PLW_HASHMAP pAllMayAttrMap = NULL; if (!pEntry || IsNullOrEmptyString(pszAttrName)) { dwError = VMDIR_ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } dwError = LwRtlCreateHashMap(&pAllMustAttrMap, LwRtlHashDigestPstrCaseless, LwRtlHashEqualPstrCaseless, NULL); BAIL_ON_VMDIR_ERROR(dwError); dwError = LwRtlCreateHashMap(&pAllMayAttrMap, LwRtlHashDigestPstrCaseless, LwRtlHashEqualPstrCaseless, NULL); BAIL_ON_VMDIR_ERROR(dwError); pAttrOC = VmDirFindAttrByName(pEntry, ATTR_OBJECT_CLASS); for (i = 0; pAttrOC && i < pAttrOC->numVals; i++) { dwError = VmDirSchemaOCNameToDescriptor( pEntry->pSchemaCtx, pAttrOC->vals[i].lberbv.bv_val, &pOCDesc); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirSchemaClassGetAllMustAttrs( pEntry->pSchemaCtx, pOCDesc, pAllMustAttrMap); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirSchemaClassGetAllMayAttrs( pEntry->pSchemaCtx, pOCDesc, pAllMayAttrMap); BAIL_ON_VMDIR_ERROR(dwError); } if (pbMust) { *pbMust = FALSE; if (LwRtlHashMapFindKey(pAllMustAttrMap, NULL, pszAttrName) == 0) { *pbMust = TRUE; } } if (pbMay) { *pbMay = FALSE; if (LwRtlHashMapFindKey(pAllMayAttrMap, NULL, pszAttrName) == 0) { *pbMay = TRUE; } } cleanup: LwRtlHashMapClear(pAllMustAttrMap, VmDirNoopHashMapPairFree, NULL); LwRtlFreeHashMap(&pAllMustAttrMap); LwRtlHashMapClear(pAllMayAttrMap, VmDirNoopHashMapPairFree, NULL); LwRtlFreeHashMap(&pAllMayAttrMap); return dwError; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s failed, error (%d)", __FUNCTION__, dwError ); goto cleanup; }
static DWORD _PopulateOperationModAttributes( LDAP *pLd, LDAPMessage *pEntry, PVDIR_OPERATION pLdapOp ) { DWORD dwError = 0; struct berval** ppValues = NULL; PLW_HASHMAP pHashMap = NULL; PSTR pszBuf = NULL; PSTR pszAttrName = NULL; PSTR pszAttrMetaData = NULL; PSTR pszAttrUsnlessMetaData = NULL; PSTR pszAttrNewMetaData = NULL; PSTR pszKey = NULL; PSTR pszValue = NULL; USN localUsn = 0; PVDIR_BERVALUE pBerValue = NULL; size_t iBerValueSize = 0; DWORD i = 0, j = 0; dwError = LwRtlCreateHashMap( &pHashMap, LwRtlHashDigestPstrCaseless, LwRtlHashEqualPstrCaseless, NULL ); BAIL_ON_VMDIR_ERROR(dwError); dwError = pLdapOp->pBEIF->pfnBEGetNextUSN(pLdapOp->pBECtx, &localUsn); BAIL_ON_VMDIR_ERROR(dwError); if (!(ppValues = ldap_get_values_len(pLd, pEntry, ATTR_ATTR_META_DATA))) { dwError = VMDIR_ERROR_SCHEMA_BAD_METADATA; BAIL_ON_VMDIR_ERROR(dwError); } for (i = 0; ppValues[i] != NULL; i++) { dwError = VmDirAllocateStringA(ppValues[i]->bv_val, &pszBuf); BAIL_ON_VMDIR_ERROR(dwError); pszAttrName = VmDirStringTokA(pszBuf, ":", &pszAttrMetaData); VmDirStringTokA(pszAttrMetaData, ":", &pszAttrUsnlessMetaData); dwError = VmDirAllocateStringPrintf( &pszAttrNewMetaData, "%ld:%s", localUsn, pszAttrUsnlessMetaData); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateStringA(pszAttrName, &pszKey); BAIL_ON_VMDIR_ERROR(dwError); dwError = LwRtlHashMapInsert(pHashMap, pszKey, pszAttrNewMetaData, NULL); BAIL_ON_VMDIR_ERROR(dwError); VMDIR_SAFE_FREE_MEMORY(pszBuf); } ldap_value_free_len(ppValues); ppValues = NULL; for (i = 0; ppszSchemaEntryAttrs[i] != NULL; i++) { if (VmDirStringCompareA(ppszSchemaEntryAttrs[i], ATTR_ATTR_META_DATA, FALSE) != 0) { ppValues = ldap_get_values_len(pLd, pEntry, ppszSchemaEntryAttrs[i]); if (ppValues) { iBerValueSize = ldap_count_values_len(ppValues); dwError = VmDirAllocateMemory( sizeof(VDIR_BERVALUE) * iBerValueSize, (PVOID*)&pBerValue); BAIL_ON_VMDIR_ERROR(dwError); if (VmDirStringCompareA(ppszSchemaEntryAttrs[i], ATTR_USN_CHANGED, FALSE) == 0) { assert(iBerValueSize == 1); dwError = VmDirAllocateStringPrintf(&pBerValue[0].lberbv_val, "%ld", localUsn); BAIL_ON_VMDIR_ERROR(dwError); pBerValue[0].lberbv_len = VmDirStringLenA(pBerValue[0].lberbv_val); pBerValue[0].bOwnBvVal = TRUE; } else { for (j = 0; j < iBerValueSize; j++) { dwError = VmDirAllocateStringA(ppValues[j]->bv_val, &pBerValue[j].lberbv_val); BAIL_ON_VMDIR_ERROR(dwError); pBerValue[j].lberbv_len = ppValues[j]->bv_len; pBerValue[j].bOwnBvVal = TRUE; } } dwError = VmDirOperationAddModReq( pLdapOp, MOD_OP_REPLACE, ppszSchemaEntryAttrs[i], pBerValue, iBerValueSize); BAIL_ON_VMDIR_ERROR(dwError); dwError = LwRtlHashMapFindKey( pHashMap, (PVOID*)&pszValue, ppszSchemaEntryAttrs[i]); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirStringCpyA( pLdapOp->request.modifyReq.mods->attr.metaData, VMDIR_MAX_ATTR_META_DATA_LEN, pszValue); BAIL_ON_VMDIR_ERROR(dwError); ldap_value_free_len(ppValues); ppValues = NULL; for (j = 0; j < iBerValueSize; j++) { VmDirFreeBervalContent(&pBerValue[j]); } VMDIR_SAFE_FREE_MEMORY(pBerValue); } } } cleanup: LwRtlHashMapClear(pHashMap, _FreeStringPair, NULL); LwRtlFreeHashMap(&pHashMap); return dwError; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s,%d failed, error(%d)", __FUNCTION__, __LINE__, dwError ); VMDIR_SAFE_FREE_MEMORY(pszBuf); VMDIR_SAFE_FREE_MEMORY(pszAttrNewMetaData); if (ppValues) { ldap_value_free_len(ppValues); } for (j = 0; j < iBerValueSize; j++) { VmDirFreeBervalContent(&pBerValue[j]); } VMDIR_SAFE_FREE_MEMORY(pBerValue); goto cleanup; }