long
LWIRecTypeLookup::GetVector(tDataListPtr List, PLWIBITVECTOR* ppVector)
{
    int macError = eDSNoErr;
    PLWIBITVECTOR pResult = NULL;
    tDataNodePtr pDataNode = NULL;
    int nNodes = 0;
    Index_t value = idx_unknown;

    macError = LWIMakeBitVector(idx_sentinel, &pResult);
    GOTO_CLEANUP_ON_MACERROR(macError);

    if (List != NULL)
    {
       nNodes = dsDataListGetNodeCount(List);

       for (int iNode = 0; iNode < nNodes; iNode++)
       {
           macError = dsDataListGetNodeAlloc(0,
                                             List,
                                             iNode+1,
                                             &pDataNode);
           GOTO_CLEANUP_ON_MACERROR(macError);
           value = GetIndex(pDataNode->fBufferData);
           if (value)
           {
              LWI_BITVECTOR_SET(pResult, value);
           }

           dsDataNodeDeAllocate(NULL, pDataNode);
           pDataNode = NULL;
       }
    }

    *ppVector = pResult;
    pResult = NULL;

cleanup:

    if (pResult)
    {
        LWIFreeBitVector(pResult);
    }

    if (pDataNode)
    {
        dsDataNodeDeAllocate(0, pDataNode);
    }

    return macError;
}
long
LWIAttrValDataQuery::Run(sDoMultiAttrValueSearchWithData* pMultiAttrValueSearchWithData, LWE_DS_FLAGS Flags, PNETADAPTERINFO pNetAdapterList)
{
    long macError = eDSNoErr;
    long macError_userQuery = eDSNoErr;
    long macError_groupQuery = eDSNoErr;
    unsigned long bytesWritten = 0;
    unsigned long nRecordsWritten = 0;
    unsigned long TotalRecords = 0;
    LWIQuery* pQuery = NULL;
    int iter = 0;
    int resultCount = 0;
    int patternListCount = 0;
    int recordTypeCount = 0;
    int recordAttributeCount = 0;
    tDataNodePtr pPatternNode = NULL;
    bool isWithData = (kDoMultipleAttributeValueSearchWithData == pMultiAttrValueSearchWithData->fType);
    tContextData HandleId = 0;
 
    LOG_ENTER("LWIAttrValDataQuery::Run - fType = %d, fResult = %d, fInNodeRef = %d, fInAttrType = %s, fInPattMatchType = 0x%04X, fInAttrInfoOnly = %s, fIOContinueData = %d, fOutDataBuff => { size = %d }",
              pMultiAttrValueSearchWithData->fType,
              pMultiAttrValueSearchWithData->fResult,
              pMultiAttrValueSearchWithData->fInNodeRef,
              pMultiAttrValueSearchWithData->fInAttrType->fBufferData,
              pMultiAttrValueSearchWithData->fInPattMatchType,
              BOOL_STRING(isWithData && pMultiAttrValueSearchWithData->fInAttrInfoOnly),
              pMultiAttrValueSearchWithData->fIOContinueData,
              pMultiAttrValueSearchWithData->fOutDataBuff->fBufferSize);

    patternListCount = dsDataListGetNodeCount(pMultiAttrValueSearchWithData->fInPatterns2MatchList);
    recordTypeCount = dsDataListGetNodeCount(pMultiAttrValueSearchWithData->fInRecTypeList);
    recordAttributeCount = isWithData ? dsDataListGetNodeCount(pMultiAttrValueSearchWithData->fInAttrTypeRequestList) : 0;

    LOG_PARAM("fInPatterns2MatchList.count = %d, fInRecTypeList.count = %d, fInAttrTypeRequestList.count = %d",
              patternListCount,
              recordTypeCount,
              recordAttributeCount);

    if (pMultiAttrValueSearchWithData->fIOContinueData != 0)
    {
        macError = GetQueryFromContextList(pMultiAttrValueSearchWithData->fIOContinueData, &pQuery);
        if (macError == eDSNoErr)
        {
            LOG("Already processed this query, handling IO continuation for result record data");
            goto HandleResponse;
        }
    }
    
    macError = LWIQuery::Create(!isWithData || !pMultiAttrValueSearchWithData->fInAttrInfoOnly,
                                true, // The query results will support fIOContinue (split large results over many calls)
                                pMultiAttrValueSearchWithData->fInNodeRef,
                                Flags,
                                pNetAdapterList,
                                &pQuery);
    GOTO_CLEANUP_ON_MACERROR(macError);

    macError = LWIRecTypeLookup::GetVector(pMultiAttrValueSearchWithData->fInRecTypeList, &pQuery->_recTypeSet);
    GOTO_CLEANUP_ON_MACERROR(macError);

    if (isWithData)
    {
        macError = LWIAttrLookup::GetVector(pMultiAttrValueSearchWithData->fInAttrTypeRequestList, &pQuery->_attributeSet);
        GOTO_CLEANUP_ON_MACERROR(macError);
    }
    else
    {
        macError = LWIAttrLookup::GetVector(kDSAttributesAll, &pQuery->_attributeSet);
        GOTO_CLEANUP_ON_MACERROR(macError);
    }

    // We support only exact (including case-insensitive) matches
    switch (pMultiAttrValueSearchWithData->fInPattMatchType)
    {
        case eDSExact:
        case eDSiExact:
            // These are fine
            break;

        default:
            LOG("Unsupported pattern match type: 0x%04X", pMultiAttrValueSearchWithData->fInPattMatchType);
            macError = eDSRecordNotFound;
            GOTO_CLEANUP_ON_MACERROR(macError);
    }

    macError = eDSInvalidRecordType;

    for (iter = 0; iter < patternListCount; iter++)
    {
        macError = dsDataListGetNodeAlloc(pMultiAttrValueSearchWithData->fInNodeRef,
                                          pMultiAttrValueSearchWithData->fInPatterns2MatchList,
                                          iter+1,
                                          &pPatternNode);
        GOTO_CLEANUP_ON_MACERROR(macError);
        
        LOG_PARAM("Searching for pattern (%s)...", pPatternNode->fBufferData);
                    
        if (pQuery->ShouldQueryUserInformation())
        {
            macError_userQuery = QueryUserInformation(pQuery,
                                                      pMultiAttrValueSearchWithData->fInAttrType->fBufferData,
                                                      pPatternNode->fBufferData);
            if (macError_userQuery != eDSNoErr)
            {
                LOG("User query failed [Error: %d]", macError_userQuery);
            }
            else
            {
                resultCount++;
            }
        }

        if (pQuery->ShouldQueryGroupInformation())
        {
            macError_groupQuery = QueryGroupInformation(pQuery,
                                                        pMultiAttrValueSearchWithData->fInAttrType->fBufferData,
                                                        pPatternNode->fBufferData);
            if (macError_groupQuery != eDSNoErr)
            {
                LOG("Group query failed [Error: %d]", macError_groupQuery);
            }
            else
            {
                resultCount++;
            }
        }
    
        if (pQuery->ShouldQueryComputerListInformation())
        {
            macError_groupQuery = QueryComputerListInformation(pQuery,
                                                               pMultiAttrValueSearchWithData->fInAttrType->fBufferData,
                                                               pPatternNode->fBufferData);
            if (macError_groupQuery != eDSNoErr)
            {
                LOG("Computer List query failed [Error: %d]", macError_groupQuery);
            }
            else
            {
                resultCount++;
            }
        }

        if (pQuery->ShouldQueryComputerGroupInformation())
        {
            macError_groupQuery = QueryComputerGroupInformation(pQuery,
                                                                pMultiAttrValueSearchWithData->fInAttrType->fBufferData,
                                                                pPatternNode->fBufferData);
            if (macError_groupQuery != eDSNoErr)
            {
                LOG("Computer Group query failed [Error: %d]", macError_groupQuery);
            }
            else
            {
                resultCount++;
            }
        }

        if (pQuery->ShouldQueryComputerInformation())
        {
            macError_groupQuery = QueryComputerInformation(pQuery,
                                                           pMultiAttrValueSearchWithData->fInAttrType->fBufferData,
                                                           pPatternNode->fBufferData);
            if (macError_groupQuery != eDSNoErr)
            {
                LOG("Computer query failed [Error: %d]", macError_groupQuery);
            }
            else
            {
                resultCount++;
            }
        }

        dsDataNodeDeAllocate(NULL, pPatternNode);
        pPatternNode = NULL;
    }

    // If both queries failed, it is a problem
    if (resultCount == 0 && (macError_userQuery != eDSNoErr) && (macError_groupQuery != eDSNoErr))
    {
       macError = (pQuery->ShouldQueryUserInformation() ? macError_userQuery : macError_groupQuery);
       GOTO_CLEANUP_ON_MACERROR(macError);
    }
    else
       macError = eDSNoErr;

HandleResponse:

    // Write the results
    macError = pQuery->WriteResponse(pMultiAttrValueSearchWithData->fOutDataBuff->fBufferData,
                                     pMultiAttrValueSearchWithData->fOutDataBuff->fBufferSize,
                                     bytesWritten,
                                     nRecordsWritten,
                                     TotalRecords);
    GOTO_CLEANUP_ON_MACERROR(macError);

    if (TotalRecords > nRecordsWritten)
    {
        macError = AddQueryToContextList(pQuery, &HandleId);
        GOTO_CLEANUP_ON_MACERROR(macError);

        pQuery = NULL;
        pMultiAttrValueSearchWithData->fIOContinueData = HandleId;
    }
    else
    {
        pMultiAttrValueSearchWithData->fIOContinueData = 0;
    }

    pMultiAttrValueSearchWithData->fOutDataBuff->fBufferLength = bytesWritten;
    pMultiAttrValueSearchWithData->fInOutMatchRecordCount = nRecordsWritten;

    if ( bytesWritten > 0 )
    {
#ifdef SHOW_ALL_DEBUG_SPEW
        LOG_BUFFER(pMultiAttrValueSearchWithData->fOutDataBuff->fBufferData, bytesWritten);
#endif
    }

cleanup:

    if (pQuery)
    {
        delete pQuery;
    }
    
    if (pPatternNode)
    {
        dsDataNodeDeAllocate(0, pPatternNode);
    }

    LOG_LEAVE("fInOutMatchRecordCount = %d, fIOContinueData = %d --> %d", pMultiAttrValueSearchWithData->fInOutMatchRecordCount, pMultiAttrValueSearchWithData->fIOContinueData, macError);

    return macError;
}
long
LWIRecordListQuery::Run(IN OUT sGetRecordList* pGetRecordList, LWE_DS_FLAGS Flags, PNETADAPTERINFO pNetAdapterList)
{
    long macError = eDSNoErr;
    long macError_userQuery = eDSNoErr;
    long macError_groupQuery = eDSNoErr;
    long macError_computerQuery = eDSNoErr;
    long macError_computergroupQuery = eDSNoErr;
    long macError_computerlistQuery = eDSNoErr;
    tDataNodePtr pDataNode = NULL;
    const char* szNames = NULL;
    unsigned long bytesWritten = 0;
    unsigned long nRecordsWritten = 0;
    unsigned long TotalRecords = 0;
    LWIQuery* pQuery = NULL;
    int iter = 0;
    int resultCount = 0;
    int recordNameCount;
    int recordTypeCount;
    int recordAttributeCount;
    tContextData HandleId = 0;

    LOG_ENTER("LWIRecordListQuery::Run - fType = %d, fResult = %d, fInNodeRef = %d, "
              "fInDataBuf = @%p { len = %d, size = %d }, fInPatternMatch = 0x%04X, "
              "fIOContinueData = %d",
              pGetRecordList->fType,
              pGetRecordList->fResult,
              pGetRecordList->fInNodeRef,
              pGetRecordList->fInDataBuff,
              pGetRecordList->fInDataBuff->fBufferLength,
              pGetRecordList->fInDataBuff->fBufferSize,
              pGetRecordList->fInPatternMatch,
              pGetRecordList->fIOContinueData);

    recordNameCount = dsDataListGetNodeCount(pGetRecordList->fInRecNameList);
    recordTypeCount = dsDataListGetNodeCount(pGetRecordList->fInRecTypeList);
    recordAttributeCount = dsDataListGetNodeCount(pGetRecordList->fInAttribTypeList);

    LOG_PARAM("fInRecNameList.count = %d, fInRecTypeList.count = %d, "
              "fInAttribTypeList.count = %d",
              recordNameCount,
              recordTypeCount,
              recordAttributeCount);

    /* Initialize the out parameters in case we return with error */
    pGetRecordList->fInDataBuff->fBufferLength = 0;
    pGetRecordList->fOutRecEntryCount = 0;

    if ((UInt32)pGetRecordList->fIOContinueData != 0 &&
        (UInt32)pGetRecordList->fIOContinueData != SPECIAL_DS_CONTINUE_HANDLE)
    {
        macError = GetQueryFromContextList(pGetRecordList->fIOContinueData, &pQuery);
        if (macError == eDSNoErr)
        {
            LOG("Already processed this query, handling IO continuation for result record data");
            goto HandleResponse;
        }
    }

    macError = LWIQuery::Create(!pGetRecordList->fInAttribInfoOnly,
                                true, // The query results will support fIOContinue (split large results over many calls)
                                pGetRecordList->fInNodeRef,
                                Flags,
                                pNetAdapterList,
                                &pQuery);
    GOTO_CLEANUP_ON_MACERROR(macError);

    macError = LWIRecTypeLookup::GetVector(pGetRecordList->fInRecTypeList, &pQuery->_recTypeSet);
    GOTO_CLEANUP_ON_MACERROR(macError);

    macError = LWIAttrLookup::GetVector(pGetRecordList->fInAttribTypeList, &pQuery->_attributeSet);
    GOTO_CLEANUP_ON_MACERROR(macError);

    for (iter = 0; iter < recordNameCount; iter++)
    {
        macError = dsDataListGetNodeAlloc( pGetRecordList->fInNodeRef,
                                           pGetRecordList->fInRecNameList,
                                           iter+1,
                                           &pDataNode );
        GOTO_CLEANUP_ON_MACERROR( macError );
        szNames = pDataNode->fBufferData;

        macError = eDSInvalidRecordType;

        if (pQuery->ShouldQueryUserInformation())
        {
            macError_userQuery = pQuery->QueryUserInformationByName(szNames);
            if (macError_userQuery != eDSNoErr)
            {
               LOG("User query failed [Error: %d]", macError_userQuery);
            }
            else
            {
                resultCount++;
            }
        }

        if (pQuery->ShouldQueryGroupInformation())
        {
            macError_groupQuery = pQuery->QueryGroupInformationByName(szNames);
            if (macError_groupQuery != eDSNoErr)
            {
               LOG("Group query failed [Error: %d]", macError_groupQuery);
            }
            else
            {
                resultCount++;
            }
        }

        if (pQuery->ShouldQueryComputerInformation())
        {
            macError_computerQuery = pQuery->QueryComputerInformationByName(szNames);
            if (macError_computerQuery != eDSNoErr)
            {
               LOG("Computer query failed [Error: %d]", macError_computerQuery);
            }
            else
            {
                resultCount++;
            }
        }

        if (pQuery->ShouldQueryComputerGroupInformation())
        {
            macError_computergroupQuery = pQuery->QueryComputerGroupInformationByName(szNames);
            if (macError_computergroupQuery != eDSNoErr)
            {
               LOG("Computer group query failed [Error: %d]", macError_computergroupQuery);
            }
            else
            {
                resultCount++;
            }
        }

        if (pQuery->ShouldQueryComputerListInformation())
        {
            macError_computerlistQuery = pQuery->QueryComputerListInformationByName(szNames);
            if (macError_computerlistQuery != eDSNoErr)
            {
               LOG("Computer list query failed [Error: %d]", macError_computerlistQuery);
            }
            else
            {
                resultCount++;
            }
        }

        dsDataNodeDeAllocate(NULL, pDataNode);
        pDataNode = NULL;
    }

    // If both queries failed, it is a problem
    if (resultCount == 0 &&
        (macError_userQuery != eDSNoErr) &&
        (macError_groupQuery != eDSNoErr) &&
        (macError_computerQuery != eDSNoErr) &&
        (macError_computergroupQuery != eDSNoErr) &&
        (macError_computerlistQuery != eDSNoErr))
    {
       macError = (pQuery->ShouldQueryUserInformation() ? macError_userQuery : macError_groupQuery);
       GOTO_CLEANUP_ON_MACERROR(macError);
    }
    else
       macError = eDSNoErr;

HandleResponse:

    // Write the results
    macError = pQuery->WriteResponse(pGetRecordList->fInDataBuff->fBufferData,
                                     pGetRecordList->fInDataBuff->fBufferSize,
                                     bytesWritten,
                                     nRecordsWritten,
                                     TotalRecords);
    GOTO_CLEANUP_ON_MACERROR(macError);

    if (TotalRecords > nRecordsWritten)
    {
        macError = AddQueryToContextList(pQuery, &HandleId);
        GOTO_CLEANUP_ON_MACERROR(macError);

        pQuery = NULL;

        pGetRecordList->fIOContinueData = HandleId;
    }
    else
    {
        pGetRecordList->fIOContinueData = 0;
    }

    pGetRecordList->fInDataBuff->fBufferLength = bytesWritten;
    pGetRecordList->fOutRecEntryCount = nRecordsWritten;

    if ( bytesWritten > 0 )
    {
#ifdef SHOW_ALL_DEBUG_SPEW
        LOG_BUFFER(pGetRecordList->fInDataBuff->fBufferData, bytesWritten);
#endif
    }

cleanup:

    if (pDataNode)
    {
        dsDataNodeDeAllocate(0, pDataNode);
    }

    if (pQuery)
    {
        delete pQuery;
    }

    if (macError == eDSBufferTooSmall)
    {
        pGetRecordList->fIOContinueData = (tContextData)SPECIAL_DS_CONTINUE_HANDLE;
    }

    LOG_LEAVE("fOutRecEntryCount = %d, fInDataBuff = { length = %d, size = %d }, fIOContinueData = %d, macError = %d",
              pGetRecordList->fOutRecEntryCount,
              pGetRecordList->fInDataBuff->fBufferLength,
              pGetRecordList->fInDataBuff->fBufferSize,
              pGetRecordList->fIOContinueData,
              macError);

    return macError;
}