ANSC_STATUS
AnscLpccoDelAllPartyAddrs
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PANSC_LPC_CONNECTOR_OBJECT      pMyObject    = (PANSC_LPC_CONNECTOR_OBJECT)hThisObject;
    PANSC_LPC_PARTY_ADDR            pPartyAddr   = (PANSC_LPC_PARTY_ADDR      )NULL;
    PSINGLE_LINK_ENTRY              pSLinkEntry  = (PSINGLE_LINK_ENTRY        )NULL;
    ULONG                           i            = 0;

    AnscAcquireLock(&pMyObject->PartyTableLock);

    for ( i = 0; i < ANSC_LPCCO_PARTY_TABLE_SIZE; i++ )
    {
        pSLinkEntry = AnscQueuePopEntry(&pMyObject->PartyTable[i]);

        while ( pSLinkEntry )
        {
            pPartyAddr  = ACCESS_ANSC_LPC_PARTY_ADDR(pSLinkEntry);
            pSLinkEntry = AnscQueuePopEntry(&pMyObject->PartyTable[i]);

            AnscFreeMemory(pPartyAddr);
        }
    }

    AnscReleaseLock(&pMyObject->PartyTableLock);

    return  ANSC_STATUS_SUCCESS;
}
ANSC_STATUS
AnscLpccoDelPartyAddr
    (
        ANSC_HANDLE                 hThisObject,
        char*                       party_name
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PANSC_LPC_CONNECTOR_OBJECT      pMyObject    = (PANSC_LPC_CONNECTOR_OBJECT)hThisObject;
    PANSC_LPC_PARTY_ADDR            pPartyAddr   = (PANSC_LPC_PARTY_ADDR      )NULL;
    PSINGLE_LINK_ENTRY              pSLinkEntry  = (PSINGLE_LINK_ENTRY        )NULL;
    ULONG                           ulHashIndex  = AnscHashString(party_name, AnscSizeOfString(party_name), ANSC_LPCCO_PARTY_TABLE_SIZE);

    AnscAcquireLock(&pMyObject->PartyTableLock);

    pSLinkEntry = AnscQueueGetFirstEntry(&pMyObject->PartyTable[ulHashIndex]);

    while ( pSLinkEntry )
    {
        pPartyAddr  = ACCESS_ANSC_LPC_PARTY_ADDR(pSLinkEntry);
        pSLinkEntry = AnscQueueGetNextEntry(pSLinkEntry);

        if ( AnscEqualString
                (
                    pPartyAddr->PartyName,
                    party_name,
                    FALSE
                ) )
        {
            AnscQueuePopEntryByLink(&pMyObject->PartyTable[ulHashIndex], &pPartyAddr->Linkage);

            AnscFreeMemory(pPartyAddr);

            break;
        }
    }

    AnscReleaseLock(&pMyObject->PartyTableLock);

    return  ANSC_STATUS_SUCCESS;
}
ANSC_STATUS
AnscLpccoConnTimerInvoke
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PANSC_LPC_CONNECTOR_OBJECT      pMyObject    = (PANSC_LPC_CONNECTOR_OBJECT)hThisObject;
    PANSC_CPC_INTERFACE             pAnscCpcIf   = (PANSC_CPC_INTERFACE       )pMyObject->hAnscCpcIf;
    PANSC_LPC_PARTY_ADDR            pPartyAddr   = (PANSC_LPC_PARTY_ADDR      )NULL;
    PSINGLE_LINK_ENTRY              pSLinkEntry  = (PSINGLE_LINK_ENTRY        )NULL;
    ULONG                           i            = 0;

    if ( !pMyObject->bActive )
    {
        return  ANSC_STATUS_SUCCESS;
    }

    AnscAcquireLock(&pMyObject->PartyTableLock);

    for ( i = 0; i < ANSC_LPCCO_PARTY_TABLE_SIZE; i++ )
    {
        pSLinkEntry = AnscQueueGetFirstEntry(&pMyObject->PartyTable[i]);

        while ( pSLinkEntry )
        {
            pPartyAddr  = ACCESS_ANSC_LPC_PARTY_ADDR(pSLinkEntry);
            pSLinkEntry = AnscQueueGetNextEntry(pSLinkEntry);

            if ( pPartyAddr->Timestamp == 0 )
            {
                continue;
            }
            else if ( (pPartyAddr->PartyState & ANSC_LPC_PARTY_STATE_connectedIn ) ||
                      (pPartyAddr->PartyState & ANSC_LPC_PARTY_STATE_connectedOut) )
            {
                continue;
            }
            else if ( pPartyAddr->PartyType == ANSC_LPC_PARTY_TYPE_manager )
            {
                if ( (pMyObject->LpcOpmode  == ANSC_LPC_OPMODE_CLIENT) &&
                     (pMyObject->bConnected == TRUE                  ) )
                {
                    pMyObject->bConnected = FALSE;
                }

                continue;
            }
            else if ( pPartyAddr->PartyType != ANSC_LPC_PARTY_TYPE_client )
            {
                continue;
            }
            else if ( pPartyAddr->RefCount > 0 )
            {
                continue;
            }

            AnscQueuePopEntryByLink(&pMyObject->PartyTable[i], &pPartyAddr->Linkage);

            if ( TRUE )
            {
                returnStatus =
                    pAnscCpcIf->NotifyEvent
                        (
                            pAnscCpcIf->hOwnerContext,
                            ANSC_CPC_EVENT_DISCONNECTED,
                            (ANSC_HANDLE)pPartyAddr
                        );
            }

            AnscFreeMemory(pPartyAddr);
        }
    }

    AnscReleaseLock(&pMyObject->PartyTableLock);

    if ( (pMyObject->LpcOpmode  == ANSC_LPC_OPMODE_CLIENT) &&
         (pMyObject->bConnected == FALSE                 ) )
    {
        returnStatus = pMyObject->ConnectToManager((ANSC_HANDLE)pMyObject);
    }

    return  ANSC_STATUS_SUCCESS;
}
ANSC_STATUS
AnscLpccoGetPartyArray
    (
        ANSC_HANDLE                 hThisObject,
        ANSC_HANDLE*                pPartyArray,
        PULONG                      pulCount
    )
{
    ANSC_STATUS                     returnStatus    = ANSC_STATUS_SUCCESS;
    PANSC_LPC_CONNECTOR_OBJECT      pMyObject       = (PANSC_LPC_CONNECTOR_OBJECT)hThisObject;
    PANSC_LPC_PARTY_ADDR            pPartyAddrArray = (PANSC_LPC_PARTY_ADDR      )NULL;
    PANSC_LPC_PARTY_ADDR            pPartyAddr      = (PANSC_LPC_PARTY_ADDR      )NULL;
    PSINGLE_LINK_ENTRY              pSLinkEntry     = (PSINGLE_LINK_ENTRY        )NULL;
    ULONG                           ulPartyMaxCount = (ULONG                     )pMyObject->GetPartyCount   ((ANSC_HANDLE)pMyObject);
    ULONG                           ulPartyAddrSize = (ULONG                     )pMyObject->GetPartyAddrSize((ANSC_HANDLE)pMyObject);
    ULONG                           ulPartyCount    = 0;
    ULONG                           i               = 0;

    if ( ulPartyMaxCount == 0 )
    {
        *pPartyArray = (ANSC_HANDLE)NULL;
        *pulCount    = 0;

        return  ANSC_STATUS_SUCCESS;
    }
    else
    {
        pPartyAddrArray = (PANSC_LPC_PARTY_ADDR)AnscAllocateMemory(ulPartyAddrSize * ulPartyMaxCount);

        if ( !pPartyAddrArray )
        {
            return  ANSC_STATUS_RESOURCES;
        }
    }

    AnscAcquireLock(&pMyObject->PartyTableLock);

    for ( i = 0; i < ANSC_LPCCO_PARTY_TABLE_SIZE; i++ )
    {
        pSLinkEntry = AnscQueueGetFirstEntry(&pMyObject->PartyTable[i]);

        while ( pSLinkEntry )
        {
            pPartyAddr  = ACCESS_ANSC_LPC_PARTY_ADDR(pSLinkEntry);
            pSLinkEntry = AnscQueueGetNextEntry(pSLinkEntry);

            AnscCopyMemory
                (
                    (void*)((ULONG)pPartyAddrArray + ulPartyCount * ulPartyAddrSize),
                    pPartyAddr,
                    pPartyAddr->StructSize
                );

            ulPartyCount++;

            if ( ulPartyCount >= ulPartyMaxCount )
            {
                break;
            }
        }

        if ( ulPartyCount >= ulPartyMaxCount )
        {
            break;
        }
    }

    AnscReleaseLock(&pMyObject->PartyTableLock);

    *pPartyArray = (ANSC_HANDLE)pPartyAddrArray;
    *pulCount    = ulPartyCount;

    return  ANSC_STATUS_SUCCESS;
}