Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

937 lines
20 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
D:\nt\private\ntos\tdi\rawwan\core\addr.c
Abstract:
TDI Entry points and support routines for Address Objects.
Revision History:
Who When What
-------- -------- ----------------------------------------------
arvindm 04-29-97 Created
Notes:
--*/
#include <precomp.h>
#define _FILENUMBER 'RDDA'
//
// Context we use to keep track of NDIS SAP registration
//
typedef struct _RWAN_REGISTER_SAP_CONTEXT
{
PRWAN_NDIS_SAP pRWanNdisSap;
CO_SAP CoSap;
} RWAN_REGISTER_SAP_CONTEXT, *PRWAN_REGISTER_SAP_CONTEXT;
TDI_STATUS
RWanTdiOpenAddress(
IN PTDI_REQUEST pTdiRequest,
IN TRANSPORT_ADDRESS UNALIGNED *pAddrList,
IN ULONG AddrListLength,
IN UINT Protocol,
IN PUCHAR pOptions
)
/*++
Routine Description:
This is the TDI entry point for opening (creating) an Address Object.
Arguments:
pTdiRequest - Pointer to the TDI Request
pAddrList - List of alternative addresses, one of which we're to open.
AddrListLength - Length of the above
Protocol - Identifies the TDI Protocol being opened.
pOptions - Unused.
Return Value:
TDI_STATUS -- TDI_SUCCESS if a new Address Object was successfully
created, TDI_BAD_ADDR if the given address isn't valid,
TDI_ADDR_IN_USE if it is a duplicate.
--*/
{
PRWAN_TDI_PROTOCOL pProtocol;
PRWAN_TDI_ADDRESS pAddrObject;
TA_ADDRESS * pTransportAddress;
TDI_STATUS Status;
INT rc;
UNREFERENCED_PARAMETER(pOptions);
//
// Initialize.
//
pAddrObject = NULL_PRWAN_TDI_ADDRESS;
Status = TDI_SUCCESS;
do
{
//
// Get our protocol structure for the protocol being opened.
//
pProtocol = RWanGetProtocolFromNumber(Protocol);
if (pProtocol == NULL_PRWAN_TDI_PROTOCOL)
{
RWANDEBUGP(DL_WARN, DC_ADDRESS,
("RWanTdiOpenAddress: unknown protocol number %d\n", Protocol));
Status = TDI_BAD_ADDR;
break;
}
//
// Does this protocol allow creation of address objects?
//
if (!pProtocol->bAllowAddressObjects)
{
RWANDEBUGP(DL_WARN, DC_ADDRESS,
("RWanTdiOpenAddress: Protocol %d/x%x doesn't allow addr objs\n",
Protocol, pProtocol));
Status = TDI_BAD_ADDR;
break;
}
//
// Go through the given Address list and find the first one
// that matches the protocol.
//
pTransportAddress = (*pProtocol->pAfInfo->AfChars.pAfSpGetValidTdiAddress)(
pProtocol->pAfInfo->AfSpContext,
pAddrList,
AddrListLength
);
if (pTransportAddress == NULL)
{
RWANDEBUGP(DL_WARN, DC_ADDRESS,
("RWanTdiOpenAddress: No valid addr for Protocol x%x in list x%x\n",
pProtocol, pAddrList));
Status = TDI_BAD_ADDR;
break;
}
RWANDEBUGP(DL_VERY_LOUD, DC_ADDRESS,
("RWanTdiOpenAddress: pProto x%x, addr x%x, type %d, length %d\n",
pProtocol,
pTransportAddress,
pTransportAddress->AddressType,
pTransportAddress->AddressLength));
//
// Allocate an Address Object.
//
pAddrObject = RWanAllocateAddressObject(pTransportAddress);
if (pAddrObject == NULL_PRWAN_TDI_ADDRESS)
{
RWANDEBUGP(DL_WARN, DC_ADDRESS,
("RWanTdiOpenAddress: couldnt allocate addr obj: %d bytes\n",
sizeof(RWAN_TDI_ADDRESS)+pTransportAddress->AddressLength));
Status = TDI_NO_RESOURCES;
break;
}
pAddrObject->pProtocol = pProtocol;
//
// Get a context for this address object from the media-specific
// module.
//
if (pAddrObject->pProtocol->pAfInfo->AfChars.pAfSpOpenAddress)
{
RWAN_STATUS RWanStatus;
RWanStatus = (*pAddrObject->pProtocol->pAfInfo->AfChars.pAfSpOpenAddress)(
pAddrObject->pProtocol->pAfInfo->AfSpContext,
(RWAN_HANDLE)pAddrObject,
&(pAddrObject->AfSpAddrContext));
if (RWanStatus != RWAN_STATUS_SUCCESS)
{
Status = RWanToTdiStatus(RWanStatus);
break;
}
RWAN_SET_BIT(pAddrObject->Flags, RWANF_AO_AFSP_CONTEXT_VALID);
}
RWAN_ACQUIRE_ADDRESS_LIST_LOCK();
//
// If this is a non-NULL address, register NDIS SAPs on all
// AF bindings for this protocol.
//
if (!((*pProtocol->pAfInfo->AfChars.pAfSpIsNullAddress)(
pProtocol->pAfInfo->AfSpContext,
pTransportAddress)))
{
//
// Add a temp ref so that the address object doesn't go away.
//
RWanReferenceAddressObject(pAddrObject); // TdiOpenAddress temp ref
Status = RWanCreateNdisSaps(pAddrObject, pProtocol);
if (Status != TDI_SUCCESS)
{
if (RWAN_IS_BIT_SET(pAddrObject->Flags, RWANF_AO_AFSP_CONTEXT_VALID))
{
(*pAddrObject->pProtocol->pAfInfo->AfChars.pAfSpCloseAddress)(
pAddrObject->AfSpAddrContext);
RWAN_RESET_BIT(pAddrObject->Flags, RWANF_AO_AFSP_CONTEXT_VALID);
}
}
//
// Get rid of the temp reference.
//
RWAN_ACQUIRE_ADDRESS_LOCK(pAddrObject);
rc = RWanDereferenceAddressObject(pAddrObject); // TdiOpenAddr temp ref
if (rc != 0)
{
RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
}
else
{
//
// The address object is gone. Meaning no SAPs got registered.
//
pAddrObject = NULL;
//
// Fix up the status only if we haven't got one already.
//
if (Status == TDI_SUCCESS)
{
Status = TDI_BAD_ADDR;
}
}
if (Status != TDI_SUCCESS)
{
RWAN_RELEASE_ADDRESS_LIST_LOCK();
break;
}
}
RWAN_ASSERT(pAddrObject != NULL);
RWanReferenceAddressObject(pAddrObject); // TdiOpenAddress ref
//
// Link this to the list of address objects on this protocol.
//
RWAN_INSERT_HEAD_LIST(&(pProtocol->AddrObjList),
&(pAddrObject->AddrLink));
RWAN_RELEASE_ADDRESS_LIST_LOCK();
//
// Fix up all return values.
//
pTdiRequest->Handle.AddressHandle = (PVOID)pAddrObject;
break;
}
while (FALSE);
if (Status != TDI_SUCCESS)
{
//
// Clean up.
//
if (pAddrObject != NULL_PRWAN_TDI_ADDRESS)
{
RWAN_FREE_MEM(pAddrObject);
}
RWANDEBUGP(DL_FATAL, DC_WILDCARD,
("OpenAddr: failure status %x\n", Status));
}
return (Status);
}
TDI_STATUS
RWanTdiSetEvent(
IN PVOID AddrObjContext,
IN INT TdiEventType,
IN PVOID Handler,
IN PVOID HandlerContext
)
/*++
Routine Description:
Set an event handler (up-call) for an address object.
Arguments:
AddrObjContext - Our context for an Address Object (pointer to it).
TdiEventType - The TDI Event for which we are given an up-call handler.
Handler - The handler function
HandlerContext - Context to be passed to the handler function.
Return Value:
TDI_STATUS - TDI_SUCCESS if the event type is a supported one, else
TDI_BAD_EVENT_TYPE
--*/
{
PRWAN_TDI_ADDRESS pAddrObject;
TDI_STATUS Status;
pAddrObject = (PRWAN_TDI_ADDRESS)AddrObjContext;
RWAN_STRUCT_ASSERT(pAddrObject, nta);
Status = TDI_SUCCESS;
RWAN_ACQUIRE_ADDRESS_LOCK(pAddrObject);
switch (TdiEventType)
{
case TDI_EVENT_CONNECT:
RWANDEBUGP(DL_VERY_LOUD, DC_ADDRESS,
("SetEvent[CONN IND]: pAddrObject x%x, Handler x%x, Ctxt x%x\n",
pAddrObject, Handler, HandlerContext));
pAddrObject->pConnInd = Handler;
pAddrObject->ConnIndContext = HandlerContext;
break;
case TDI_EVENT_DISCONNECT:
RWANDEBUGP(DL_VERY_LOUD, DC_ADDRESS,
("SetEvent[DISC IND]: pAddrObject x%x, Handler x%x, Ctxt x%x\n",
pAddrObject, Handler, HandlerContext));
pAddrObject->pDisconInd = Handler;
pAddrObject->DisconIndContext = HandlerContext;
break;
case TDI_EVENT_ERROR:
RWANDEBUGP(DL_VERY_LOUD, DC_ADDRESS,
("SetEvent[ERRORIND]: pAddrObject x%x, Handler x%x, Ctxt x%x\n",
pAddrObject, Handler, HandlerContext));
pAddrObject->pErrorInd = Handler;
pAddrObject->ErrorIndContext = HandlerContext;
break;
case TDI_EVENT_RECEIVE:
RWANDEBUGP(DL_VERY_LOUD, DC_ADDRESS,
("SetEvent[RECV IND]: pAddrObject x%x, Handler x%x, Ctxt x%x\n",
pAddrObject, Handler, HandlerContext));
pAddrObject->pRcvInd = Handler;
pAddrObject->RcvIndContext = HandlerContext;
break;
default:
Status = TDI_BAD_EVENT_TYPE;
break;
}
RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
return (Status);
}
TDI_STATUS
RWanTdiCloseAddress(
IN PTDI_REQUEST pTdiRequest
)
/*++
Routine Description:
This is the TDI entry point for closing (deleting) an Address Object.
Arguments:
pTdiRequest - Pointer to the TDI Request
Return Value:
TDI_STATUS -- TDI_SUCCESS if we successfully deleted the address
object immediately, TDI_PENDING if we have to complete some operations
(e.g. deregister NDIS SAP) before we can complete this.
--*/
{
TDI_STATUS Status;
PRWAN_TDI_ADDRESS pAddrObject;
PRWAN_TDI_PROTOCOL pProtocol;
INT rc;
#if DBG
RWAN_IRQL EntryIrq, ExitIrq;
#endif // DBG
RWAN_GET_ENTRY_IRQL(EntryIrq);
pAddrObject = (PRWAN_TDI_ADDRESS)pTdiRequest->Handle.AddressHandle;
RWAN_STRUCT_ASSERT(pAddrObject, nta);
pProtocol = pAddrObject->pProtocol;
RWANDEBUGP(DL_EXTRA_LOUD, DC_BIND,
("TdiCloseAddr: pAddrObj x%x, RefCnt %d\n",
pAddrObject, pAddrObject->RefCount));
//
// Delete this from the list of address objects on this protocol.
//
RWAN_ACQUIRE_ADDRESS_LIST_LOCK();
RWAN_DELETE_FROM_LIST(&(pAddrObject->AddrLink));
RWAN_RELEASE_ADDRESS_LIST_LOCK();
//
// Tell the media-specific module that this address object is closing.
//
if (RWAN_IS_BIT_SET(pAddrObject->Flags, RWANF_AO_AFSP_CONTEXT_VALID))
{
(*pAddrObject->pProtocol->pAfInfo->AfChars.pAfSpCloseAddress)(
pAddrObject->AfSpAddrContext);
RWAN_RESET_BIT(pAddrObject->Flags, RWANF_AO_AFSP_CONTEXT_VALID);
}
RWAN_ACQUIRE_ADDRESS_LOCK(pAddrObject);
#if DBG
if (!RWAN_IS_LIST_EMPTY(&pAddrObject->SapList) ||
!RWAN_IS_LIST_EMPTY(&pAddrObject->IdleConnList) ||
!RWAN_IS_LIST_EMPTY(&pAddrObject->ListenConnList) ||
!RWAN_IS_LIST_EMPTY(&pAddrObject->ActiveConnList)
)
{
RWAN_ASSERT(pAddrObject->RefCount > 1);
}
#endif // DBG
rc = RWanDereferenceAddressObject(pAddrObject); // CloseAddress deref
if (rc == 0)
{
Status = TDI_SUCCESS;
}
else
{
//
// Mark this address object as closing, so that we
// complete this operation when the reference count
// falls to 0.
//
RWAN_SET_BIT(pAddrObject->Flags, RWANF_AO_CLOSING);
RWANDEBUGP(DL_LOUD, DC_BIND,
("TdiCloseAddr: will pend, pAddrObj x%x, RefCnt %d, DelNotify x%x\n",
pAddrObject, pAddrObject->RefCount, pTdiRequest->RequestNotifyObject));
RWAN_SET_DELETE_NOTIFY(&pAddrObject->DeleteNotify,
pTdiRequest->RequestNotifyObject,
pTdiRequest->RequestContext);
//
// Deregister all NDIS SAPs attached to this Address Object.
//
RWanDeleteNdisSaps(pAddrObject);
Status = TDI_PENDING;
}
RWAN_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
return (Status);
}
TDI_STATUS
RWanCreateNdisSaps(
IN PRWAN_TDI_ADDRESS pAddrObject,
IN PRWAN_TDI_PROTOCOL pProtocol
)
/*++
Routine Description:
Create NDIS SAPs on behalf of the given TDI Address Object.
We create NDIS SAPs on all AF opens that match the specified
TDI protocol.
Arguments:
pAddrObject - Pointer to our TDI Address Object
pProtocol - Pointer to TDI protocol to which the addr object belongs
Return Value:
TDI_STATUS -- this is TDI_SUCCESS if we started SAP registration
on atleast one NDIS AF open, TDI_NOT_ASSOCIATED otherwise.
--*/
{
TDI_STATUS Status;
PCO_SAP pCoSap;
PRWAN_NDIS_SAP pSap;
PLIST_ENTRY pSapEntry;
PLIST_ENTRY pNextSapEntry;
PRWAN_NDIS_ADAPTER pAdapter;
PLIST_ENTRY pAdEntry;
PRWAN_NDIS_AF pAf;
PLIST_ENTRY pAfEntry;
PRWAN_NDIS_AF_INFO pAfInfo;
pAfInfo = pProtocol->pAfInfo;
RWANDEBUGP(DL_VERY_LOUD, DC_BIND,
("CreateNdisSaps: pAddrObject x%x, pProtocol x%x, pAfInfo x%x\n",
pAddrObject, pProtocol, pAfInfo));
RWAN_ASSERT(RWAN_IS_LIST_EMPTY(&pAddrObject->SapList));
RWAN_ACQUIRE_GLOBAL_LOCK();
//
// Prepare NDIS SAP structures for each NDIS AF open that matches
// this protocol.
//
for (pAdEntry = pRWanGlobal->AdapterList.Flink;
pAdEntry != &(pRWanGlobal->AdapterList);
pAdEntry = pAdEntry->Flink)
{
pAdapter = CONTAINING_RECORD(pAdEntry, RWAN_NDIS_ADAPTER, AdapterLink);
RWANDEBUGP(DL_EXTRA_LOUD, DC_BIND,
("CreateNdisSaps: looking at adapter x%x\n", pAdapter));
for (pAfEntry = pAdapter->AfList.Flink;
pAfEntry != &(pAdapter->AfList);
pAfEntry = pAfEntry->Flink)
{
pAf = CONTAINING_RECORD(pAfEntry, RWAN_NDIS_AF, AfLink);
RWANDEBUGP(DL_EXTRA_LOUD, DC_BIND,
("CreateNdisSaps: looking at AF x%x, AfInfo x%x\n",
pAf, pAf->pAfInfo));
if (pAf->pAfInfo == pAfInfo)
{
//
// This NDIS AF open matches the TDI protocol for which
// the address object is opened. We will create an NDIS
// SAP here.
//
ULONG SapSize;
//
// Allocate a new SAP structure.
//
SapSize = sizeof(RWAN_NDIS_SAP);
RWAN_ALLOC_MEM(pSap, RWAN_NDIS_SAP, SapSize);
if (pSap == NULL_PRWAN_NDIS_SAP)
{
RWANDEBUGP(DL_WARN, DC_ADDRESS,
("RWanCreateNdisSaps: failed to alloc SAP %d bytes\n",
SapSize));
continue;
}
//
// Fill it in.
//
RWAN_SET_SIGNATURE(pSap, nsp);
pSap->pAddrObject = pAddrObject;
pSap->NdisSapHandle = NULL;
pSap->pNdisAf = pAf;
pSap->pCoSap = NULL;
//
// Link to all SAPs associated with address object.
//
RWAN_INSERT_TAIL_LIST(&(pAddrObject->SapList),
&(pSap->AddrObjLink));
RWanReferenceAddressObject(pAddrObject); // NDIS SAP ref
}
}
}
RWAN_RELEASE_GLOBAL_LOCK();
//
// Now go through the SAP list and call NDIS to register them.
//
for (pSapEntry = pAddrObject->SapList.Flink;
pSapEntry != &(pAddrObject->SapList);
pSapEntry = pNextSapEntry)
{
RWAN_STATUS RWanStatus;
NDIS_STATUS NdisStatus;
pSap = CONTAINING_RECORD(pSapEntry, RWAN_NDIS_SAP, AddrObjLink);
pNextSapEntry = pSap->AddrObjLink.Flink;
//
// Convert the transport address to NDIS SAP format.
//
RWanStatus = (*pAfInfo->AfChars.pAfSpTdi2NdisSap)(
pAfInfo->AfSpContext,
pAddrObject->AddressType,
pAddrObject->AddressLength,
pAddrObject->pAddress,
&(pSap->pCoSap));
if (RWanStatus == RWAN_STATUS_SUCCESS)
{
RWAN_ASSERT(pSap->pCoSap != NULL);
//
// Register this SAP with the Call Manager.
//
NdisStatus = NdisClRegisterSap(
pSap->pNdisAf->NdisAfHandle,
(NDIS_HANDLE)pSap,
pSap->pCoSap,
&(pSap->NdisSapHandle)
);
}
else
{
NdisStatus = NDIS_STATUS_FAILURE;
}
if (NdisStatus != NDIS_STATUS_PENDING)
{
RWanNdisRegisterSapComplete(
NdisStatus,
(NDIS_HANDLE)pSap,
pSap->pCoSap,
pSap->NdisSapHandle
);
}
}
if (!RWAN_IS_LIST_EMPTY(&pAddrObject->SapList))
{
Status = TDI_SUCCESS;
}
else
{
Status = RWanNdisToTdiStatus(pAddrObject->SapStatus);
RWANDEBUGP(DL_WARN, DC_WILDCARD,
("CreateNdisSaps: NdisStatus %x, TdiStatus %x\n",
pAddrObject->SapStatus, Status));
}
return (Status);
}
VOID
RWanNdisRegisterSapComplete(
IN NDIS_STATUS NdisStatus,
IN NDIS_HANDLE OurSapContext,
IN PCO_SAP pCoSap,
IN NDIS_HANDLE NdisSapHandle
)
/*++
Routine Description:
This is called by NDIS to signal completion of a previously
pended call to NdisClRegisterSap.
Arguments:
NdisStatus - Final status of SAP registration.
OurSapContext - Points to our NDIS SAP structure.
pCoSap - The parameter we passed to NdisClRegisterSap. Not used.
NdisSapHandle - If NdisStatus indicates success, this contains the
assigned handle for this SAP.
Return Value:
None
--*/
{
PRWAN_NDIS_SAP pSap;
PRWAN_TDI_ADDRESS pAddrObject;
INT rc;
PRWAN_NDIS_AF_INFO pAfInfo;
PRWAN_NDIS_AF pAf;
UNREFERENCED_PARAMETER(pCoSap);
pSap = (PRWAN_NDIS_SAP)OurSapContext;
RWAN_STRUCT_ASSERT(pSap, nsp);
pAddrObject = pSap->pAddrObject;
pAfInfo = pSap->pNdisAf->pAfInfo;
pCoSap = pSap->pCoSap;
pSap->pCoSap = NULL;
RWANDEBUGP(DL_LOUD, DC_BIND,
("RegisterSapComplete: pAddrObj x%x, pSap x%x, Status x%x\n",
pAddrObject, pSap, NdisStatus));
if (NdisStatus == NDIS_STATUS_SUCCESS)
{
pSap->NdisSapHandle = NdisSapHandle;
pAf = pSap->pNdisAf;
//
// Link this SAP to the list of all SAPs on the AF.
//
RWAN_ACQUIRE_AF_LOCK(pAf);
RWAN_INSERT_TAIL_LIST(&pAf->NdisSapList,
&pSap->AfLink);
RWanReferenceAf(pAf); // New SAP registered.
RWAN_RELEASE_AF_LOCK(pAf);
}
else
{
//
// Failed to register this SAP. Clean up.
//
RWAN_ACQUIRE_ADDRESS_LOCK(pAddrObject);
pAddrObject->SapStatus = NdisStatus;
RWAN_DELETE_FROM_LIST(&(pSap->AddrObjLink));
rc = RWanDereferenceAddressObject(pAddrObject); // Reg SAP failed
if (rc != 0)
{
RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
}
RWAN_FREE_MEM(pSap);
}
//
// If the AF-specific module had given us a SAP structure,
// return it now.
//
if (pCoSap != NULL)
{
(*pAfInfo->AfChars.pAfSpReturnNdisSap)(
pAfInfo->AfSpContext,
pCoSap
);
}
return;
}
VOID
RWanDeleteNdisSaps(
IN PRWAN_TDI_ADDRESS pAddrObject
)
/*++
Routine Description:
Delete all NDIS SAPs on the given address object. We call NDIS
to deregister them.
Arguments:
pAddrObject - Pointer to TDI Address Object
Return Value:
None
--*/
{
PRWAN_NDIS_SAP pSap;
PLIST_ENTRY pSapEntry;
PLIST_ENTRY pFirstSapEntry;
PLIST_ENTRY pNextSapEntry;
NDIS_STATUS NdisStatus;
NDIS_HANDLE NdisSapHandle;
//
// Mark all SAPs as closing, while we hold a lock to the address object.
//
for (pSapEntry = pAddrObject->SapList.Flink;
pSapEntry != &(pAddrObject->SapList);
pSapEntry = pNextSapEntry)
{
pSap = CONTAINING_RECORD(pSapEntry, RWAN_NDIS_SAP, AddrObjLink);
pNextSapEntry = pSap->AddrObjLink.Flink;
RWAN_SET_BIT(pSap->Flags, RWANF_SAP_CLOSING);
}
//
// Unlink the SAP list from the Address Object.
// This will protect us if at all we re-enter this routine.
//
pFirstSapEntry = pAddrObject->SapList.Flink;
RWAN_INIT_LIST(&pAddrObject->SapList);
RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
for (pSapEntry = pFirstSapEntry;
pSapEntry != &(pAddrObject->SapList);
pSapEntry = pNextSapEntry)
{
pSap = CONTAINING_RECORD(pSapEntry, RWAN_NDIS_SAP, AddrObjLink);
pNextSapEntry = pSap->AddrObjLink.Flink;
NdisSapHandle = pSap->NdisSapHandle;
RWAN_ASSERT(NdisSapHandle != NULL);
RWANDEBUGP(DL_LOUD, DC_BIND,
("RWanDeleteNdisSaps: pAddrObj x%x, pSap x%x, pAf x%x\n",
pAddrObject, pSap, pSap->pNdisAf));
NdisStatus = NdisClDeregisterSap(NdisSapHandle);
if (NdisStatus != NDIS_STATUS_PENDING)
{
RWanNdisDeregisterSapComplete(
NdisStatus,
(NDIS_HANDLE)pSap
);
}
}
}
VOID
RWanNdisDeregisterSapComplete(
IN NDIS_STATUS NdisStatus,
IN NDIS_HANDLE ProtocolSapContext
)
/*++
Routine Description:
This is called by NDIS to signal completion of a previously
pended call to NdisClDeregisterSap.
We unlink the SAP from the two lists it is linked to: the
Address Object's SAP list and the AF's SAP list.
Arguments:
NdisStatus - Final status of SAP deregistration.
Return Value:
None
--*/
{
PRWAN_NDIS_SAP pSap;
PRWAN_TDI_ADDRESS pAddrObject;
PRWAN_NDIS_AF pAf;
INT rc;
RWAN_ASSERT(NdisStatus == NDIS_STATUS_SUCCESS);
pSap = (PRWAN_NDIS_SAP)ProtocolSapContext;
RWAN_STRUCT_ASSERT(pSap, nsp);
RWANDEBUGP(DL_VERY_LOUD, DC_BIND,
("RWanDeregSapComplete: pSap x%x, pAddrObj x%x, pAf x%x\n",
pSap, pSap->pAddrObject, pSap->pNdisAf));
pAddrObject = pSap->pAddrObject;
//
// Unlink the SAP from the Address Object.
//
RWAN_ACQUIRE_ADDRESS_LOCK(pAddrObject);
RWAN_DELETE_FROM_LIST(&(pSap->AddrObjLink));
rc = RWanDereferenceAddressObject(pAddrObject); // SAP dereg complete
if (rc != 0)
{
RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
}
//
// Unlink the SAP from the AF.
//
pAf = pSap->pNdisAf;
RWAN_STRUCT_ASSERT(pAf, naf);
RWAN_ACQUIRE_AF_LOCK(pAf);
RWAN_DELETE_FROM_LIST(&(pSap->AfLink));
rc = RWanDereferenceAf(pAf); // SAP deregister complete
if (rc != 0)
{
RWAN_RELEASE_AF_LOCK(pAf);
}
RWAN_FREE_MEM(pSap);
}