DWORD VmDirStringErrorA( PSTR buffer, size_t numberOfElements, int errnum ) { return VmDirStringNCpyA( buffer, numberOfElements, strerror(errnum), numberOfElements - 1 ); }
VOID _Test_VmDirStringNCpyA_NullDestinationString( PVMDIR_TEST_STATE pState ) { DWORD dwError = 0; dwError = VmDirStringNCpyA(NULL, 4, "test", 4); TestAssertEquals(dwError, ERROR_INVALID_PARAMETER); }
VOID _Test_VmDirStringNCpyA_SourceStringTooLong( PVMDIR_TEST_STATE pState ) { DWORD dwError = 0; CHAR szDestination[4] = { 'a' }; dwError = VmDirStringNCpyA( szDestination, VMDIR_ARRAY_SIZE(szDestination), "Hello, world!", 7); TestAssertEquals(dwError, ERROR_INVALID_PARAMETER); TestAssertEquals(szDestination[0], 'a'); }
VOID _Test_VmDirStringNCpyA_EmptySourceStringWrongCount( PVMDIR_TEST_STATE pState ) { DWORD dwError = 0; CHAR szDestination[16] = { 'a' }; dwError = VmDirStringNCpyA( szDestination, VMDIR_ARRAY_SIZE(szDestination), "", 10); TestAssertEquals(dwError, 0); TestAssertEquals(szDestination[0], '\0'); }
VOID _Test_VmDirStringNCpyA_NullSourceString( PVMDIR_TEST_STATE pState ) { DWORD dwError = 0; CHAR szDestination[16] = { 'a' }; dwError = VmDirStringNCpyA( szDestination, VMDIR_ARRAY_SIZE(szDestination), NULL, 10); TestAssertEquals(dwError, ERROR_INVALID_PARAMETER); TestAssertEquals(szDestination[0], 'a'); }
VOID _Test_VmDirStringNCpyA_CallShouldFailCountMatchesSize( PVMDIR_TEST_STATE pState ) { DWORD dwError = 0; CHAR szBuffer[4] = { 'a' }; dwError = VmDirStringNCpyA( szBuffer, VMDIR_ARRAY_SIZE(szBuffer), "abcd", 4); TestAssertEquals(dwError, ERROR_INVALID_PARAMETER); TestAssertEquals(szBuffer[0], 'a'); }
VOID _Test_VmDirStringNCpyA_CallShouldSucceedWithTruncation( PVMDIR_TEST_STATE pState ) { DWORD dwError = 0; CHAR szDestination[6] = { 'a' }; dwError = VmDirStringNCpyA( szDestination, VMDIR_ARRAY_SIZE(szDestination), "Hello, world!", VMDIR_ARRAY_SIZE(szDestination) - 1); TestAssertEquals(dwError, 0); TestAssertStrEquals(szDestination, "Hello"); }
VOID _Test_VmDirStringNCpyA_EmptySourceStringRightCount( PVMDIR_TEST_STATE pState ) { DWORD dwError = 0; CHAR szDestination[16] = { '\0' }; // // This call will yield different results on windows and linux. On // the former we call the _s version of strncpy so the string's first byte // will be NULL, regardless of what it is coming into the call. However, // on linux the string will be untouched after the call. // dwError = VmDirStringNCpyA( szDestination, VMDIR_ARRAY_SIZE(szDestination), "", 0); TestAssertEquals(dwError, 0); TestAssertEquals(szDestination[0], '\0'); }
static int IsAttrInReplScope( VDIR_OPERATION * op, char * attrType, char * attrMetaData, BOOLEAN * inScope, PSTR* ppszErrorMsg ) { int retVal = LDAP_SUCCESS; PLW_HASHTABLE_NODE pNode = NULL; char origInvocationId[VMDIR_GUID_STR_LEN]; USN origUsn = VmDirStringToLA( VmDirStringRChrA( attrMetaData, ':' ) + 1, NULL, 10 ); int rc = 0; PSTR pszLocalErrorMsg = NULL; *inScope = FALSE; // attrMetaData format is: <local USN>:<version no>:<originating server ID>:<originating time>:<originating USN> VmDirStringNCpyA( origInvocationId, VMDIR_GUID_STR_LEN, VmDirStringChrA( VmDirStringChrA( attrMetaData, ':' ) + 1, ':') + 1, VMDIR_GUID_STR_LEN - 1); origInvocationId[VMDIR_GUID_STR_LEN - 1] = '\0'; // Skip the attribute: // - if the originating server for the current state is same as the requesting server or if it is one of those // attributes that have "local" scope only. E.g. sending ATTR_LAST_LOCAL_USN_PROCESSED and // ATTR_UP_TO_DATE_VECTOR, causes continuous back-forth replication of Replication Agreements and Server // entries between various servers. assert( op->syncReqCtrl != NULL ); if ((attrType != NULL && (VmDirStringCompareA( attrType, ATTR_LAST_LOCAL_USN_PROCESSED, FALSE) == 0 || VmDirStringCompareA( attrType, ATTR_UP_TO_DATE_VECTOR, FALSE) == 0 || VmDirStringCompareA( attrType, VDIR_ATTRIBUTE_SEQUENCE_RID, FALSE) == 0))) { // Reset metaData value so that we don't send local only attribute back. attrMetaData[0] = '\0'; *inScope = FALSE; goto cleanup; } else if ( attrType != NULL && (VmDirStringCompareA( attrType, ATTR_USN_CHANGED, FALSE) == 0)) { ; // always send uSNChanged. (PR 1573117) } else if (VmDirStringCompareA( origInvocationId, op->syncReqCtrl->value.syncReqCtrlVal.reqInvocationId.lberbv.bv_val,TRUE ) == 0) { // Change is originated from the requesting server. // Reset metaData value so that we don't send metaData as well as this attribute back. attrMetaData[0] = '\0'; *inScope = FALSE; goto cleanup; } else { rc = LwRtlHashTableFindKey( op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector, &pNode, origInvocationId ); rc = LwNtStatusToWin32Error(rc); if (rc != 0 && rc != ERROR_NOT_FOUND) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "IsAttrInReplScope: LwRtlHashTableFindKey failed for origInvocationId: %s", origInvocationId ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "LwRtlHashTableFindKey failed."); } if (pNode == NULL) // Attribute is to be sent in the result entry. { UptoDateVectorEntry * utdVectorEntry = NULL; VDIR_BERVALUE bvServerId = VDIR_BERVALUE_INIT; if (VmDirAllocateMemory( sizeof( UptoDateVectorEntry ), (PVOID *)&utdVectorEntry) != 0) { retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "IsAttrInReplScope: BervalContentDup failed."); } bvServerId.lberbv.bv_val = origInvocationId; bvServerId.lberbv.bv_len = VmDirStringLenA( origInvocationId ); if (VmDirBervalContentDup( &bvServerId, &utdVectorEntry->invocationId ) != 0) { retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "IsAttrInReplScope: BervalContentDup failed."); } utdVectorEntry->currMaxOrigUsnProcessed = origUsn; LwRtlHashTableResizeAndInsert( op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector, &utdVectorEntry->Node, &pNode); assert( pNode == NULL ); // assert the key of added node is unique } else { UptoDateVectorEntry * utdVectorEntry = NULL; utdVectorEntry = (UptoDateVectorEntry *)LW_STRUCT_FROM_FIELD(pNode, UptoDateVectorEntry, Node); if (origUsn > utdVectorEntry->reqLastOrigUsnProcessed ) { // Attribute is to be sent in the result entry. // Update if origUsn of this attribute is > the current highest if (origUsn > utdVectorEntry->currMaxOrigUsnProcessed ) { utdVectorEntry->currMaxOrigUsnProcessed = origUsn; } } else { VMDIR_LOG_VERBOSE( LDAP_DEBUG_REPL_ATTR, "IsAttrInReplScope: Attribute: %s, metaData: %s, replication scope = FALSE", attrType, attrMetaData ); // Reset metaData value so that we don't send metaData for this attribute back. attrMetaData[0] = '\0'; *inScope = FALSE; goto cleanup; } } } VMDIR_LOG_INFO( LDAP_DEBUG_REPL_ATTR, "IsAttrInReplScope: Attribute: %s, metaData: %s, replication scope = TRUE", attrType, attrMetaData ); *inScope = TRUE; cleanup: if (ppszErrorMsg) { *ppszErrorMsg = pszLocalErrorMsg; } else { VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); } return( retVal ); error: goto cleanup; }
/* * This generic search with pagination is new and isn't mature. Please be * careful with the * scope, base, and use an indexed filter. * Note that ulPageSize == 0 will ignore paging. */ DWORD VmDirFilterInternalSearch( PCSTR pszBaseDN, int searchScope, PCSTR pszFilter, unsigned long ulPageSize, PSTR *ppszPageCookie, PVDIR_ENTRY_ARRAY pEntryArray ) { DWORD dwError = 0; VDIR_OPERATION searchOP = {0}; VDIR_BERVALUE bervDN = VDIR_BERVALUE_INIT; PVDIR_FILTER pFilter = NULL; PVDIR_LDAP_CONTROL showPagedResultsCtrl = NULL; PSTR pszPageCookie = NULL; if ( !pszBaseDN || !pszFilter || !pEntryArray || (ulPageSize != 0 && ppszPageCookie == NULL)) { dwError = VMDIR_ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } if (ulPageSize != 0) { dwError = VmDirAllocateMemory( sizeof(VDIR_LDAP_CONTROL), (PVOID *)&showPagedResultsCtrl ); BAIL_ON_VMDIR_ERROR(dwError); showPagedResultsCtrl->value.pagedResultCtrlVal.pageSize = ulPageSize; if (ppszPageCookie && *ppszPageCookie) { VmDirStringNCpyA(showPagedResultsCtrl->value.pagedResultCtrlVal.cookie, VMDIR_ARRAY_SIZE(showPagedResultsCtrl->value.pagedResultCtrlVal.cookie), *ppszPageCookie, VMDIR_ARRAY_SIZE(showPagedResultsCtrl->value.pagedResultCtrlVal.cookie) - 1); } else { showPagedResultsCtrl->value.pagedResultCtrlVal.cookie[0] = '\0'; } } dwError = VmDirInitStackOperation( &searchOP, VDIR_OPERATION_TYPE_INTERNAL, LDAP_REQ_SEARCH, NULL ); BAIL_ON_VMDIR_ERROR(dwError); bervDN.lberbv.bv_val = (PSTR)pszBaseDN; bervDN.lberbv.bv_len = VmDirStringLenA(pszBaseDN); searchOP.pBEIF = VmDirBackendSelect( pszBaseDN ); assert(searchOP.pBEIF); dwError = VmDirBervalContentDup( &bervDN, &searchOP.reqDn); BAIL_ON_VMDIR_ERROR(dwError); searchOP.request.searchReq.scope = searchScope; dwError = StrFilterToFilter(pszFilter, &pFilter); BAIL_ON_VMDIR_ERROR(dwError); searchOP.request.searchReq.filter = pFilter; pFilter = NULL; // search request takes over pFilter searchOP.showPagedResultsCtrl = showPagedResultsCtrl; dwError = VmDirInternalSearch( &searchOP ); BAIL_ON_VMDIR_ERROR(dwError); // caller takes over searchOP.internalSearchEntryArray contents pEntryArray->iSize = searchOP.internalSearchEntryArray.iSize; pEntryArray->pEntry = searchOP.internalSearchEntryArray.pEntry; searchOP.internalSearchEntryArray.iSize = 0; searchOP.internalSearchEntryArray.pEntry = NULL; if (showPagedResultsCtrl) { dwError = VmDirAllocateStringA(showPagedResultsCtrl->value.pagedResultCtrlVal.cookie, &pszPageCookie); BAIL_ON_VMDIR_ERROR(dwError); *ppszPageCookie = pszPageCookie; pszPageCookie = NULL; } cleanup: VMDIR_SAFE_FREE_MEMORY(showPagedResultsCtrl); VmDirFreeOperationContent(&searchOP); if (pFilter) { DeleteFilter(pFilter); } return dwError; error: goto cleanup; }
static int _ParsePagedResultControlVal( VDIR_OPERATION * op, BerValue * controlValue, // Input: control value encoded as ber VDIR_PAGED_RESULT_CONTROL_VALUE * pageResultCtrlVal, // Output VDIR_LDAP_RESULT * lr // Output ) { int retVal = LDAP_SUCCESS; BerElementBuffer berbuf; BerElement * ber = (BerElement *)&berbuf; PSTR pszLocalErrorMsg = NULL; PSTR pszCookie = NULL; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "_ParsePagedResultControlVal: Start." ); if (!op) { retVal = LDAP_PROTOCOL_ERROR; BAIL_ON_VMDIR_ERROR( retVal ); } ber_init2( ber, controlValue, LBER_USE_DER ); /* http://www.ietf.org/rfc/rfc2696.txt * * The searchControlValue is an OCTET STRING wrapping the BER-encoded version of the following SEQUENCE: * * realSearchControlValue ::= SEQUENCE { * size INTEGER (0..maxInt), * -- requested page size from client * -- result set size estimate from server * cookie OCTET STRING } */ if (ber_scanf(ber, "{ia}", &pageResultCtrlVal->pageSize, &pszCookie) == LBER_ERROR) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "_ParsePagedResultControlVal: ber_scanf failed while parsing " "pageSize and cookie in the page result control value" ); lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Error in reading pageSize and cookie in the page result control value"); } if (pageResultCtrlVal->pageSize == 0) { retVal = LDAP_CANCELLED; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "Search query was cancelled."); BAIL_ON_VMDIR_ERROR(retVal); } VmDirStringNCpyA( pageResultCtrlVal->cookie, VMDIR_ARRAY_SIZE(pageResultCtrlVal->cookie), pszCookie, VMDIR_ARRAY_SIZE(pageResultCtrlVal->cookie) - 1); VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "pageSize:%d", pageResultCtrlVal->pageSize ); VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "cookie:%s", pageResultCtrlVal->cookie ); cleanup: if (pszCookie) { ber_memfree(pszCookie); } // Even in the error case, syncDoneCtrl should be freed during operation delete. VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "_ParsePagedResultControlVal: End." ); VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); return retVal; error: VMDIR_APPEND_ERROR_MSG(lr->pszErrMsg, pszLocalErrorMsg); goto cleanup; }
int ParseRequestControls( VDIR_OPERATION * op, VDIR_LDAP_RESULT * lr ) { int retVal = LDAP_SUCCESS; ber_tag_t tag = LBER_ERROR; ber_len_t len = 0; char * endOfCtrlsMarker = NULL; VDIR_LDAP_CONTROL ** control = &(op->reqControls); BerValue lberBervType = {0}; BerValue lberBervCtlValue = {0}; PSTR pszLocalErrorMsg = NULL; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseRequestControls: Begin." ); *control = NULL; #ifndef _WIN32 if (ber_pvt_ber_remaining(op->ber) != 0) #else if (LBER_DEFAULT != ber_peek_tag (op->ber, &len)) #endif { if (ber_peek_tag( op->ber, &len ) != LDAP_TAG_CONTROLS ) { lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: Request controls expected, but something else is there in the PDU."); } // Get controls. ber_first_element => skip the sequence header, set the cursor at the 1st control in the SEQ of SEQ for( tag = ber_first_element( op->ber, &len, &endOfCtrlsMarker ); tag != LBER_ERROR; tag = ber_next_element( op->ber, &len, endOfCtrlsMarker ) ) { // m => in-place if (ber_scanf( op->ber, "{m", &lberBervType ) == LBER_ERROR) { lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls Error in reading control type from the PDU."); } if ( VmDirLogGetMask() & LDAP_DEBUG_ARGS) { VMDIR_LOG_INFO( LDAP_DEBUG_ARGS, " Request Control: %s", lberBervType.bv_val ); } if (VmDirAllocateMemory( sizeof( VDIR_LDAP_CONTROL), (PVOID *)control ) != 0) { retVal = lr->errCode = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: VmDirAllocateMemory failed"); } // type points into in-place ber and does NOT own its content (*control)->type = lberBervType.bv_val; (*control)->criticality = FALSE; tag = ber_peek_tag( op->ber, &len ); if (tag == LBER_BOOLEAN) { ber_int_t criticality; if (ber_scanf( op->ber, "b", &criticality) == LBER_ERROR) { lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: Error in reading control criticality from the PDU."); } if (criticality) { (*control)->criticality = TRUE; } tag = ber_peek_tag( op->ber, &len ); } if (tag == LBER_OCTETSTRING) { if (ber_scanf( op->ber, "m", &lberBervCtlValue) == LBER_ERROR) { lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: ber_scanf failed while parsing the control value."); } } // SJ-TBD: Make sure that the control appears only once in the request, and it is present only in a search // request if (VmDirStringCompareA( (*control)->type, LDAP_CONTROL_SYNC, TRUE ) == 0) { if (VmDirdGetRunMode() != VMDIR_RUNMODE_NORMAL) { // Why block out-bound replication when catching up during restore mode? // // Reason: Partners have high-water-mark (lastLocalUsn) corresponding to this replica that is being // restored. If out-bound replication is not blocked while restore/catching-up is going on, originating // or replicated updates (if this replica is the only partner) made between the current-local-usn and // high-water-marks, that partners remember, will not get replicated out (even if the invocationId // has been fixed/changed). retVal = lr->errCode = LDAP_UNWILLING_TO_PERFORM; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: Server not in normal mode, not allowing outward replication."); } if ((retVal = ParseSyncRequestControlVal( op, &lberBervCtlValue, &((*control)->value.syncReqCtrlVal), lr)) != LDAP_SUCCESS) { BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: ParseSyncRequestControlVal failed."); } op->syncReqCtrl = *control; } if (VmDirStringCompareA( (*control)->type, VDIR_LDAP_CONTROL_SHOW_DELETED_OBJECTS, TRUE ) == 0) { op->showDeletedObjectsCtrl = *control; } if (VmDirStringCompareA( (*control)->type, VDIR_LDAP_CONTROL_SHOW_MASTER_KEY, TRUE ) == 0) { op->showMasterKeyCtrl = *control; } if (VmDirStringCompareA((*control)->type, LDAP_CONTROL_CONSISTENT_WRITE, TRUE ) == 0) { op->strongConsistencyWriteCtrl = *control; } if (VmDirStringCompareA((*control)->type, VDIR_LDAP_CONTROL_MANAGEDDSAIT, TRUE ) == 0) { op->manageDsaITCtrl = *control; } if (VmDirStringCompareA( (*control)->type, LDAP_CONTROL_PAGEDRESULTS, TRUE ) == 0) { retVal = _ParsePagedResultControlVal( op, &lberBervCtlValue, &((*control)->value.pagedResultCtrlVal), lr); if (retVal != LDAP_SUCCESS) { BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: _ParsePagedResultControlVal failed."); } op->showPagedResultsCtrl = *control; } if (VmDirStringCompareA( (*control)->type, LDAP_CONTROL_CONDITIONAL_WRITE, TRUE ) == 0) { retVal = _ParseCondWriteControlVal( op, &lberBervCtlValue, &((*control)->value.condWriteCtrlVal), lr); if (retVal != LDAP_SUCCESS) { BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: _ParseConditionalWriteControlVal failed."); } op->pCondWriteCtrl = *control; } if (VmDirStringCompareA( (*control)->type, LDAP_APPEND_ENTRIES_CONTROL, TRUE ) == 0) { retVal = _ParseAppendEntriesControlVal( op, &lberBervCtlValue, &((*control)->value.appendEntriesCtrlVal), lr); if (retVal != LDAP_SUCCESS) { BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: _ParseAppendEntriesControlVal failed."); } op->appendEntriesCtrl = *control; } if (VmDirStringCompareA( (*control)->type, LDAP_REQUEST_VOTE_CONTROL, TRUE ) == 0) { retVal = _ParseRequestVoteControlVal( op, &lberBervCtlValue, &((*control)->value.requestVoteCtrlVal), lr); if (retVal != LDAP_SUCCESS) { BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: _ParseRequestVoteControlVal failed."); } op->requestVoteCtrl = *control; } if (VmDirStringCompareA( (*control)->type, VMDIR_LDAP_CONTROL_TXN_SPEC, TRUE ) == 0) { retVal = VmDirAllocateMemory(lberBervCtlValue.bv_len+1, (PVOID*)&((*control)->value.txnSpecCtrlVal).pszTxnId); BAIL_ON_VMDIR_ERROR(retVal); VmDirStringNCpyA(((*control)->value.txnSpecCtrlVal).pszTxnId, lberBervCtlValue.bv_len+1, lberBervCtlValue.bv_val, lberBervCtlValue.bv_len); op->txnSpecCtrl = *control; op->pBECtx->pszTxnId = (op->txnSpecCtrl->value.txnSpecCtrlVal).pszTxnId; } if ( ber_scanf( op->ber, "}") == LBER_ERROR ) // end of control { lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseRequestControls: ber_scanf failed while parsing the end of control"); } control = &((*control)->next); } retVal = LDAP_SUCCESS; } cleanup: VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseRequestControls: End." ); VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); return retVal; error: DeleteControls(&(op->reqControls)); if (pszLocalErrorMsg) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, pszLocalErrorMsg); VMDIR_APPEND_ERROR_MSG(lr->pszErrMsg, pszLocalErrorMsg); } goto cleanup; }