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.
 
 
 
 
 
 

877 lines
13 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
D:\nt\private\ntos\tdi\rawwan\core\utils.c
Abstract:
Revision History:
Who When What
-------- -------- ----------------------------------------------
arvindm 05-07-97 Created
Notes:
--*/
#include <precomp.h>
#define _FILENUMBER 'LITU'
RWAN_STATUS
RWanInitGlobals(
IN PDRIVER_OBJECT pDriverObject
)
/*++
Routine Description:
Initialize global data structures.
Arguments:
pDriverObject - Points to our driver object, from DriverEntry.
Return Value:
RWAN_STATUS_SUCCESS if initialized successfully, else an appropriate
error code.
--*/
{
RWAN_STATUS RWanStatus;
pRWanGlobal = &RWanGlobals;
RWAN_ZERO_MEM(pRWanGlobal, sizeof(RWanGlobals));
RWAN_SET_SIGNATURE(pRWanGlobal, nlg);
RWAN_INIT_LIST(&pRWanGlobal->AfInfoList);
RWAN_INIT_LIST(&pRWanGlobal->ProtocolList);
RWAN_INIT_LIST(&pRWanGlobal->AdapterList);
RWAN_INIT_GLOBAL_LOCK();
RWAN_INIT_ADDRESS_LIST_LOCK();
RWAN_INIT_CONN_TABLE_LOCK();
RWAN_INIT_EVENT_STRUCT(&pRWanGlobal->Event);
pRWanGlobal->MaxConnections = RWanMaxTdiConnections;
#ifdef NT
pRWanGlobal->pDriverObject = pDriverObject;
RWAN_INIT_LIST(&pRWanGlobal->DeviceObjList);
#endif // NT
RWanStatus = RWanInitReceive();
if (RWanStatus == RWAN_STATUS_SUCCESS)
{
RWanStatus = RWanInitSend();
if (RWanStatus != RWAN_STATUS_SUCCESS)
{
RWanShutdownReceive();
}
}
return (RWanStatus);
}
VOID
RWanDeinitGlobals(
VOID
)
/*++
Routine Description:
The flip of RWanInitGlobals.
Arguments:
None
Return Value:
None
--*/
{
RWAN_FREE_EVENT_STRUCT(&pRWanGlobal->Event);
RWAN_FREE_GLOBAL_LOCK();
if (pRWanGlobal->pConnTable != NULL)
{
RWAN_FREE_MEM(pRWanGlobal->pConnTable);
pRWanGlobal->pConnTable = NULL;
}
RWanShutdownReceive();
RWanShutdownSend();
}
PRWAN_TDI_PROTOCOL
RWanGetProtocolFromNumber(
IN UINT Protocol
)
/*++
Routine Description:
Return the TDI Protocol info block that represents the given
TDI protocol number.
Arguments:
Protocol - The TDI protocol number
Return Value:
Pointer to TDI Protocol block if found, else NULL.
--*/
{
PLIST_ENTRY pAfInfoEntry;
PRWAN_NDIS_AF_INFO pAfInfo;
PLIST_ENTRY pProtocolEntry;
PRWAN_TDI_PROTOCOL pProtocol;
BOOLEAN bFound = FALSE;
RWAN_ACQUIRE_GLOBAL_LOCK();
for (pAfInfoEntry = pRWanGlobal->AfInfoList.Flink;
pAfInfoEntry != &(pRWanGlobal->AfInfoList);
pAfInfoEntry = pAfInfoEntry->Flink)
{
pAfInfo = CONTAINING_RECORD(pAfInfoEntry, RWAN_NDIS_AF_INFO, AfInfoLink);
for (pProtocolEntry = pAfInfo->TdiProtocolList.Flink;
pProtocolEntry != &(pAfInfo->TdiProtocolList);
pProtocolEntry = pProtocolEntry->Flink)
{
pProtocol = CONTAINING_RECORD(pProtocolEntry, RWAN_TDI_PROTOCOL, AfInfoLink);
if (pProtocol->TdiProtocol == Protocol)
{
bFound = TRUE;
break;
}
}
if (bFound)
{
break;
}
}
RWAN_RELEASE_GLOBAL_LOCK();
if (!bFound)
{
pProtocol = NULL;
}
return (pProtocol);
}
TA_ADDRESS *
RWanGetValidAddressFromList(
IN TRANSPORT_ADDRESS UNALIGNED *pAddrList,
IN PRWAN_TDI_PROTOCOL pProtocol
)
/*++
Routine Description:
Go through the given transport address list, and return the first
valid protocol address that we find.
Valid address: one that matches the address type and length for
the specified TDI protocol.
Arguments:
pAddrList - Points to list of addresses
pProtocol - Points to TDI Protocol block
Return Value:
Pointer to the first valid address in the list if found, else NULL.
--*/
{
INT i;
TA_ADDRESS * pAddr;
pAddr = (TA_ADDRESS *)pAddrList->Address;
for (i = 0; i < pAddrList->TAAddressCount; i++)
{
if ((pAddr->AddressType == pProtocol->SockAddressFamily) &&
(pAddr->AddressLength >= pProtocol->MaxAddrLength))
{
return (pAddr);
}
pAddr = (TA_ADDRESS *)
((PUCHAR)(pAddr->Address) + pAddr->AddressLength);
}
return (NULL);
}
PRWAN_TDI_CONNECTION
RWanAllocateConnObject(
VOID
)
/*++
Routine Description:
Allocate a TDI Connection object.
Arguments:
None
Return Value:
Pointer to allocated Connection Object, or NULL.
--*/
{
PRWAN_TDI_CONNECTION pConnObject;
RWAN_ALLOC_MEM(pConnObject, RWAN_TDI_CONNECTION, sizeof(RWAN_TDI_CONNECTION));
if (pConnObject != NULL)
{
RWAN_ZERO_MEM(pConnObject, sizeof(RWAN_TDI_CONNECTION));
RWAN_SET_SIGNATURE(pConnObject, ntc);
RWAN_INIT_LOCK(&(pConnObject->Lock));
#if DBG
pConnObject->ntcd_sig = ' gbD';
#endif
}
return (pConnObject);
}
VOID
RWanReferenceConnObject(
IN PRWAN_TDI_CONNECTION pConnObject
)
/*++
Routine Description:
Add a reference to the specified Connection Object.
Arguments:
pConnObject - Pointer to the TDI Connection Object.
Locks on Entry:
pConnObject
Locks on Exit:
pConnObject
Return Value:
None
--*/
{
RWAN_STRUCT_ASSERT(pConnObject, ntc);
pConnObject->RefCount++;
}
INT
RWanDereferenceConnObject(
IN PRWAN_TDI_CONNECTION pConnObject
)
/*++
Routine Description:
Dereference the specified Connection Object. If the reference
count goes down to 0, free it.
Arguments:
pConnObject - Pointer to the TDI Connection Object.
Locks on Entry:
pConnObject
Locks on Exit:
pConnObject, iff it hasn't been freed.
Return Value:
INT - The resulting reference count.
--*/
{
INT RefCount;
RWAN_DELETE_NOTIFY DeleteNotify;
RWAN_STRUCT_ASSERT(pConnObject, ntc);
RefCount = --pConnObject->RefCount;
if (RefCount == 0)
{
DeleteNotify = pConnObject->DeleteNotify;
RWAN_RELEASE_CONN_LOCK(pConnObject);
RWANDEBUGP(DL_EXTRA_LOUD, DC_UTIL,
("Derefed away: pConnObj x%x, Notify x%x\n",
pConnObject, DeleteNotify.pDeleteRtn));
if (DeleteNotify.pDeleteRtn)
{
(*DeleteNotify.pDeleteRtn)(DeleteNotify.DeleteContext, TDI_SUCCESS, 0);
}
RWAN_FREE_MEM(pConnObject);
}
return (RefCount);
}
PRWAN_TDI_ADDRESS
RWanAllocateAddressObject(
IN TA_ADDRESS * pTransportAddress
)
/*++
Routine Description:
Allocate a TDI Address object.
Arguments:
pTransportAddress - Points to transport address for which this
Address Object is our context.
Return Value:
Pointer to allocated Address Object, or NULL.
--*/
{
PRWAN_TDI_ADDRESS pAddrObject;
ULONG Size;
NDIS_STATUS Status;
Size = sizeof(RWAN_TDI_ADDRESS) +
pTransportAddress->AddressLength;
RWAN_ALLOC_MEM(pAddrObject, RWAN_TDI_ADDRESS, Size);
if (pAddrObject != NULL)
{
RWAN_ZERO_MEM(pAddrObject, Size);
RWAN_SET_SIGNATURE(pAddrObject, nta);
RWAN_INIT_LOCK(&(pAddrObject->Lock));
Status = NDIS_STATUS_SUCCESS;
try
{
pAddrObject->AddressType = pTransportAddress->AddressType;
pAddrObject->AddressLength = pTransportAddress->AddressLength;
pAddrObject->pAddress = (PVOID)((PUCHAR)pAddrObject + sizeof(RWAN_TDI_ADDRESS));
RWAN_COPY_MEM(pAddrObject->pAddress,
pTransportAddress->Address,
pTransportAddress->AddressLength);
}
except (EXCEPTION_EXECUTE_HANDLER)
{
Status = NDIS_STATUS_FAILURE;
}
if (Status != NDIS_STATUS_SUCCESS)
{
RWAN_FREE_MEM(pAddrObject);
pAddrObject = NULL;
}
else
{
RWAN_INIT_LIST(&pAddrObject->IdleConnList);
RWAN_INIT_LIST(&pAddrObject->ListenConnList);
RWAN_INIT_LIST(&pAddrObject->ActiveConnList);
RWAN_INIT_LIST(&pAddrObject->SapList);
RWAN_INIT_EVENT_STRUCT(&pAddrObject->Event);
}
}
return (pAddrObject);
}
VOID
RWanReferenceAddressObject(
IN PRWAN_TDI_ADDRESS pAddrObject
)
/*++
Routine Description:
Add a reference to the specified Address Object.
Arguments:
pAddrObject - Pointer to the TDI Address Object.
Locks on Entry:
pAddrObject
Locks on Exit:
pAddrObject
Return Value:
None
--*/
{
RWAN_STRUCT_ASSERT(pAddrObject, nta);
pAddrObject->RefCount++;
}
INT
RWanDereferenceAddressObject(
IN PRWAN_TDI_ADDRESS pAddrObject
)
/*++
Routine Description:
Dereference the specified Address Object. If the reference
count goes down to 0, free it.
Arguments:
pAddrObject - Pointer to the TDI Address Object.
Locks on Entry:
pAddrObject
Locks on Exit:
pAddrObject, iff it hasn't been freed.
Return Value:
INT - The resulting reference count.
--*/
{
INT RefCount;
RWAN_DELETE_NOTIFY DeleteNotify;
RWAN_STRUCT_ASSERT(pAddrObject, nta);
RefCount = --pAddrObject->RefCount;
if (RefCount == 0)
{
RWAN_ASSERT(RWAN_IS_LIST_EMPTY(&pAddrObject->IdleConnList));
RWAN_ASSERT(RWAN_IS_LIST_EMPTY(&pAddrObject->ActiveConnList));
RWAN_ASSERT(RWAN_IS_LIST_EMPTY(&pAddrObject->ListenConnList));
RWAN_ASSERT(RWAN_IS_LIST_EMPTY(&pAddrObject->SapList));
DeleteNotify = pAddrObject->DeleteNotify;
RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
RWANDEBUGP(DL_EXTRA_LOUD, DC_UTIL,
("Derefed away: pAddrObj x%x, Notify x%x\n",
pAddrObject, DeleteNotify.pDeleteRtn));
if (DeleteNotify.pDeleteRtn)
{
(*DeleteNotify.pDeleteRtn)(DeleteNotify.DeleteContext, (UINT)TDI_ADDR_DELETED, 0);
}
RWAN_FREE_MEM(pAddrObject);
}
return (RefCount);
}
PRWAN_NDIS_AF
RWanAllocateAf(
VOID
)
/*++
Routine Description:
Allocate an NDIS AF block.
Arguments:
None
Return Value:
Pointer to allocated NDIS AF Block, or NULL.
--*/
{
PRWAN_NDIS_AF pAf;
RWAN_ALLOC_MEM(pAf, RWAN_NDIS_AF, sizeof(RWAN_NDIS_AF));
if (pAf != NULL)
{
RWAN_ZERO_MEM(pAf, sizeof(RWAN_NDIS_AF));
RWAN_SET_SIGNATURE(pAf, naf);
RWAN_INIT_LOCK(&(pAf->Lock));
RWAN_INIT_LIST(&(pAf->NdisVcList));
RWAN_INIT_LIST(&(pAf->NdisSapList));
}
RWANDEBUGP(DL_WARN, DC_WILDCARD,
("Allocated AF x%x\n", pAf));
return (pAf);
}
VOID
RWanReferenceAf(
IN PRWAN_NDIS_AF pAf
)
/*++
Routine Description:
Add a reference to the specified NDIS AF Block.
Arguments:
pAf - Pointer to the NDIS AF Block.
Locks on Entry:
pAf
Locks on Exit:
pAf
Return Value:
None
--*/
{
RWAN_STRUCT_ASSERT(pAf, naf);
pAf->RefCount++;
}
INT
RWanDereferenceAf(
IN PRWAN_NDIS_AF pAf
)
/*++
Routine Description:
Dereference the specified NDIS AF Block. If the reference
count goes down to 0, free it. Some additional work if
freeing this: unlink from the adapter, and check if the
adapter is unbinding.
Arguments:
pAf - Pointer to the NDIS AF Block.
Locks on Entry:
pAf
Locks on Exit:
pAf, iff it hasn't been freed.
Return Value:
INT - The resulting reference count.
--*/
{
INT RefCount;
RWAN_DELETE_NOTIFY DeleteNotify;
PRWAN_NDIS_ADAPTER pAdapter;
RWAN_STRUCT_ASSERT(pAf, naf);
RefCount = --pAf->RefCount;
if (RefCount == 0)
{
DeleteNotify = pAf->DeleteNotify;
pAdapter = pAf->pAdapter;
RWAN_RELEASE_AF_LOCK(pAf);
RWAN_ACQUIRE_GLOBAL_LOCK();
//
// Unlink from list of AF opens for this NDIS AF
//
RWAN_DELETE_FROM_LIST(&(pAf->AfInfoLink));
RWAN_RELEASE_GLOBAL_LOCK();
RWAN_ACQUIRE_ADAPTER_LOCK(pAdapter);
//
// Unlink from list of AF opens on this adapter.
//
if (RWAN_IS_BIT_SET(pAf->Flags, RWANF_AF_IN_ADAPTER_LIST))
{
RWAN_DELETE_FROM_LIST(&(pAf->AfLink));
}
//
// See if we just deleted the last AF on this adapter, and
// we are in the process of unbinding from this adapter.
//
if (RWAN_IS_LIST_EMPTY(&pAdapter->AfList) &&
RWAN_IS_BIT_SET(pAdapter->Flags, RWANF_AD_UNBIND_PENDING))
{
RWanCloseAdapter(pAdapter);
//
// Adapter lock is released within the above.
//
}
else
{
RWAN_RELEASE_ADAPTER_LOCK(pAdapter);
}
RWANDEBUGP(DL_EXTRA_LOUD, DC_UTIL,
("Derefed away: pAf x%x, Notify x%x\n",
pAf, DeleteNotify.pDeleteRtn));
if (DeleteNotify.pDeleteRtn)
{
(*DeleteNotify.pDeleteRtn)(DeleteNotify.DeleteContext, TDI_SUCCESS, 0);
}
RWAN_FREE_MEM(pAf);
}
return (RefCount);
}
#if 0
VOID
RWanReferenceAdapter(
IN PRWAN_NDIS_ADAPTER pAdapter
)
/*++
Routine Description:
Add a reference to the specified NDIS ADAPTER Block.
Arguments:
pAdapter - Pointer to the NDIS ADAPTER Block.
Locks on Entry:
pAdapter
Locks on Exit:
pAdapter
Return Value:
None
--*/
{
RWAN_STRUCT_ASSERT(pAdapter, nad);
pAdapter->RefCount++;
}
INT
RWanDereferenceAdapter(
IN PRWAN_NDIS_ADAPTER pAdapter
)
/*++
Routine Description:
Dereference the specified NDIS ADAPTER Block. If the reference
count goes down to 0, free it.
Arguments:
pAdapter - Pointer to the NDIS ADAPTER Block.
Locks on Entry:
pAdapter
Locks on Exit:
pAdapter, iff it hasn't been freed.
Return Value:
INT - The resulting reference count.
--*/
{
INT RefCount;
RWAN_DELETE_NOTIFY DeleteNotify;
RWAN_STRUCT_ASSERT(pAdapter, nad);
RefCount = --pAdapter->RefCount;
if (RefCount == 0)
{
DeleteNotify = pAdapter->DeleteNotify;
RWAN_RELEASE_ADAPTER_LOCK(pAdapter);
if (DeleteNotify.pDeleteRtn)
{
(*DeleteNotify.pDeleteRtn)(DeleteNotify.DeleteContext, TDI_SUCCESS, 0);
}
RWAN_FREE_MEM(pAdapter);
}
return (RefCount);
}
#endif // 0
TDI_STATUS
RWanNdisToTdiStatus(
IN NDIS_STATUS Status
)
/*++
Routine Description:
Convert an NDIS Status code to an equivalent TDI code.
TBD: RWanNdisToTdiStatus: support more NDIS status codes.
Arguments:
Status - NDIS status code.
Return Value:
TDI status.
--*/
{
TDI_STATUS TdiStatus;
switch (Status)
{
case NDIS_STATUS_SUCCESS:
TdiStatus = TDI_SUCCESS;
break;
case NDIS_STATUS_RESOURCES:
case NDIS_STATUS_VC_NOT_ACTIVATED:
case NDIS_STATUS_VC_NOT_AVAILABLE:
TdiStatus = TDI_NO_RESOURCES;
break;
case NDIS_STATUS_SAP_IN_USE:
TdiStatus = TDI_ADDR_IN_USE;
break;
default:
TdiStatus = TDI_NOT_ACCEPTED;
break;
}
return (TdiStatus);
}