|
|
/*++
Copyright (c) 1996-1997 Microsoft Corporation
Module Name:
apiutil.c
Abstract:
This module contains the traffic control api utils
Author:
Jim Stewart ( jstew ) August 22, 1996
Revision History:
Ofer Bar (oferbar) Oct 1, 1997 --*/
#include "precomp.h"
#pragma hdrstop
#include <initguid.h>
#define INITGUID
#include "ntddtc.h"
static BOOLEAN _init = FALSE;
#if 0
// Name of the DLL to load
const CHAR IpHlpApiDllName[] = "iphlpapi";
// Names of the functions called in IPHLPAPI
const CHAR GET_IF_ENTRY[] = "GetIfEntry"; const CHAR GET_IP_ADDR_TABLE[] = "GetIpAddrTable"; const CHAR GET_BEST_ROUTE[] = "GetBestRoute";
IPROUTE_IF IpRouteTab; #endif
TCHAR SzBuf[MAX_PATH];
//
VOID MarkAllNodesForClosing( PINTERFACE_STRUC pInterface, STATE stateToMark ) /*++
Description: This routine will mark all flows and filters on a INTERFACE_STRUC (a client's interface struct) as close FORCED_KERNELCLOSE or EXIT_CLEANUP. Please note that it is already called with the global lock held.
Arguments:
pInterface - ptr to the interface stateToMark - the state to mark the nodes (FORCED_KERNELCLOSE or EXIT_CLEANUP)
Return Value:
nothing
--*/
{ PLIST_ENTRY pEntry, pFilterEntry; PFLOW_STRUC pFlow; PFILTER_STRUC pFilter;
ASSERT((stateToMark == FORCED_KERNELCLOSE) || (stateToMark == EXIT_CLEANUP));
pEntry = pInterface->FlowList.Flink;
while (pEntry != &pInterface->FlowList) { pFlow = CONTAINING_RECORD(pEntry, FLOW_STRUC, Linkage);
//
// For each flow and filter, first check if the user is trying to close it
// if that is the case, do nothing, otherwise, mark it
GetLock(pFlow->Lock);
if (QUERY_STATE(pFlow->State) == OPEN) {
// Cleanup from under teh user...
SET_STATE(pFlow->State, stateToMark);
} else {
ASSERT(IsListEmpty(&pFlow->FilterList)); // There's nothing to be done here.
IF_DEBUG(WARNINGS) { WSPRINT(("Against a forced close - Flow is removed by the user\n", pFlow));
} }
pFilterEntry = pFlow->FilterList.Flink;
while (pFilterEntry != &pFlow->FilterList) {
pFilter = CONTAINING_RECORD(pFilterEntry, FILTER_STRUC, Linkage);
GetLock(pFilter->Lock);
if (QUERY_STATE(pFilter->State) == OPEN) { // Cleanup from under teh user...
SET_STATE(pFilter->State, stateToMark); } else { // There's nothing to be done here.
IF_DEBUG(WARNINGS) { WSPRINT(("Against a forced close - Filter is removed by the user\n", pFilter)); } } pFilterEntry = pFilterEntry->Flink; FreeLock(pFilter->Lock);
}
pEntry = pEntry->Flink; FreeLock(pFlow->Lock); }
}
VOID CloseOpenFlows( IN PINTERFACE_STRUC pInterface )
/*++
Description: This routine closes any flows that are open on an interface.
Arguments:
pInterface - ptr to the interface
Return Value:
nothing
--*/ { DWORD Status = NO_ERROR; PLIST_ENTRY pEntry; PFLOW_STRUC pFlow;
GetLock( pGlobals->Lock ); pEntry = pInterface->FlowList.Flink;
while (pEntry != &pInterface->FlowList) { pFlow = CONTAINING_RECORD( pEntry, FLOW_STRUC, Linkage );
GetLock(pFlow->Lock);
if ((QUERY_STATE(pFlow->State) == FORCED_KERNELCLOSE) || (QUERY_STATE(pFlow->State) == EXIT_CLEANUP)) {
pEntry = pEntry->Flink; FreeLock(pFlow->Lock);
IF_DEBUG(SHUTDOWN) { WSPRINT(( "Closing Flow: 0x%X\n", pFlow)); }
Status = DeleteFlow( pFlow, TRUE );
IF_DEBUG(SHUTDOWN) { WSPRINT(("CloseOpenFlows: DeleteFlow returned=0x%X\n", Status)); }
} else {
pEntry = pEntry->Flink; FreeLock(pFlow->Lock);
}
} FreeLock( pGlobals->Lock );
}
VOID CloseOpenFilters( IN PFLOW_STRUC pFlow )
/*++
Description: This routine closes any filters that are open on a flow.
Arguments:
pFlow - ptr to the flow
Return Value:
nothing
--*/ { DWORD Status = NO_ERROR; PLIST_ENTRY pEntry; PFILTER_STRUC pFilter;
IF_DEBUG(SHUTDOWN) { WSPRINT(( "CloseOpenFilters: Closing all Open Filters\n" )); }
GetLock( pGlobals->Lock ); pEntry = pFlow->FilterList.Flink;
while (pEntry != &pFlow->FilterList) { pFilter = CONTAINING_RECORD( pEntry, FILTER_STRUC, Linkage );
GetLock(pFilter->Lock);
if ((QUERY_STATE(pFilter->State) == FORCED_KERNELCLOSE) || (QUERY_STATE(pFilter->State) == EXIT_CLEANUP)) { // we can take a ref here, but we own it anyways!
pEntry = pEntry->Flink; FreeLock(pFilter->Lock);
Status = DeleteFilter( pFilter );
IF_DEBUG(SHUTDOWN) { WSPRINT(( "CloseOpenFilters: DeleteFilter returned=0x%X\n", Status)); } //ASSERT(Status == NO_ERROR);
} else {
pEntry = pEntry->Flink; FreeLock(pFilter->Lock);
IF_DEBUG(SHUTDOWN) { WSPRINT(( "CloseOpenFilters: DeleteFilter (%x) was skipped because its state (%d)\n", pFilter, pFilter->State)); }
} } FreeLock( pGlobals->Lock );
}
VOID DeleteFlowStruc( IN PFLOW_STRUC pFlow )
/*++
Description:
This routine frees the handle and memory associated with the structure.
Arguments:
pFlow - ptr to the flow
Return Value:
nothing
--*/ { if(pFlow->PendingEvent) CloseHandle(pFlow->PendingEvent);
DeleteLock(pFlow->Lock);
if (pFlow->pGenFlow) { FreeMem(pFlow->pGenFlow); pFlow->GenFlowLen = 0; }
if (pFlow->pGenFlow1) { FreeMem(pFlow->pGenFlow1); pFlow->GenFlowLen1 = 0; }
if (pFlow->pClassMapFlow) FreeMem(pFlow->pClassMapFlow);
if (pFlow->pClassMapFlow1) FreeMem(pFlow->pClassMapFlow1);
FreeMem(pFlow); }
VOID DeleteFilterStruc( IN PFILTER_STRUC pFilter )
/*++
Description:
This routine frees the handle and memory associated with the structure.
Arguments:
pFIlter
Return Value:
nothing
--*/ {
if (pFilter->pGpcFilter) FreeMem(pFilter->pGpcFilter);
DeleteLock(pFilter->Lock);
FreeMem(pFilter);
}
PTC_IFC GetTcIfc( IN LPWSTR pInterfaceName ) { PTC_IFC pIfc = NULL; PLIST_ENTRY pHead, pEntry; DWORD Status = NO_ERROR;
GetLock(pGlobals->Lock);
pHead = &pGlobals->TcIfcList;
pEntry = pHead->Flink;
while (pEntry != pHead && pIfc == NULL) {
pIfc = CONTAINING_RECORD(pEntry, TC_IFC, Linkage);
__try { if (wcsncmp(pInterfaceName, pIfc->InstanceName, wcslen(pIfc->InstanceName)) != 0) { //
// not found
//
pIfc = NULL;
}
} __except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode();
IF_DEBUG(ERRORS) { WSPRINT(("GetTcIfc: Invalid pInterfaceName(%x) Exception: = 0x%X\n", pInterfaceName, Status )); } FreeLock(pGlobals->Lock); return NULL; }
pEntry = pEntry->Flink; }
FreeLock(pGlobals->Lock);
return pIfc; }
PTC_IFC GetTcIfcWithRef( IN LPWSTR pInterfaceName, IN ULONG RefType ) { PTC_IFC pIfc = NULL; PLIST_ENTRY pHead, pEntry; DWORD Status = NO_ERROR;
GetLock(pGlobals->Lock);
pHead = &pGlobals->TcIfcList;
pEntry = pHead->Flink;
while (pEntry != pHead && pIfc == NULL) {
pIfc = CONTAINING_RECORD(pEntry, TC_IFC, Linkage);
__try { if (wcsncmp(pInterfaceName, pIfc->InstanceName, wcslen(pIfc->InstanceName)) != 0) { //
// not found
//
pIfc = NULL;
}
} __except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode();
IF_DEBUG(ERRORS) { WSPRINT(("GetTcIfc: Invalid pInterfaceName(%x) Exception: = 0x%X\n", pInterfaceName, Status )); } FreeLock(pGlobals->Lock); return NULL; }
pEntry = pEntry->Flink;
}
if (pIfc) {
GetLock(pIfc->Lock);
if (QUERY_STATE(pIfc->State)== OPEN) {
FreeLock(pIfc->Lock); REFADD(&pIfc->RefCount, RefType); FreeLock(pGlobals->Lock); return pIfc;
} else {
FreeLock(pIfc->Lock); FreeLock(pGlobals->Lock); return NULL;
}
} else { FreeLock(pGlobals->Lock); return NULL;
}
}
DWORD UpdateTcIfcList( IN LPWSTR InstanceName, IN ULONG IndicationBufferSize, IN PTC_INDICATION_BUFFER IndicationBuffer, IN DWORD IndicationCode ) { DWORD Status = NO_ERROR; PTC_IFC pTcIfc; ULONG l; PADDRESS_LIST_DESCRIPTOR pAddrListDesc;
switch (IndicationCode) {
case TC_NOTIFY_IFC_UP:
//
// Allocate a new interface descriptor structure
//
l = IndicationBufferSize - FIELD_OFFSET(TC_INDICATION_BUFFER,InfoBuffer) - FIELD_OFFSET(TC_SUPPORTED_INFO_BUFFER, AddrListDesc);
CreateKernelInterfaceStruc(&pTcIfc, l);
if (pTcIfc) { //
// copy the instance name string data
//
wcscpy(pTcIfc->InstanceName, InstanceName); pTcIfc->InstanceNameLength = wcslen(InstanceName) * sizeof(WCHAR); //
// copy the instance ID string data
//
pTcIfc->InstanceIDLength = IndicationBuffer->InfoBuffer.InstanceIDLength; memcpy((PVOID)pTcIfc->InstanceID, (PVOID)IndicationBuffer->InfoBuffer.InstanceID, pTcIfc->InstanceIDLength); pTcIfc->InstanceID[pTcIfc->InstanceIDLength/sizeof(WCHAR)] = L'\0'; //
// copy the instance data
// in this case - the network address
//
pTcIfc->AddrListBytesCount = l; RtlCopyMemory( pTcIfc->pAddressListDesc, &IndicationBuffer->InfoBuffer.AddrListDesc, l ); if (NO_ERROR != GetInterfaceIndex(pTcIfc->pAddressListDesc, &pTcIfc->InterfaceIndex, &pTcIfc->SpecificLinkCtx)) { pTcIfc->InterfaceIndex = IF_UNKNOWN; pTcIfc->SpecificLinkCtx = IF_UNKNOWN;
}
//
//
// Add the structure to the global linked list
//
GetLock(pTcIfc->Lock); SET_STATE(pTcIfc->State, OPEN); FreeLock(pTcIfc->Lock);
GetLock( pGlobals->Lock ); InsertTailList(&pGlobals->TcIfcList, &pTcIfc->Linkage ); FreeLock( pGlobals->Lock );
#if 0
//
// there's a new TC inetrface, check the GPC client list
//
OpenGpcClients(pTcIfc); #endif
} else {
Status = ERROR_NOT_ENOUGH_MEMORY;
}
break;
case TC_NOTIFY_IFC_CLOSE:
pTcIfc = GetTcIfc(InstanceName); REFDEL(&pTcIfc->RefCount, 'KIFC');
break;
case TC_NOTIFY_IFC_CHANGE: pTcIfc = GetTcIfc(InstanceName);
if (pTcIfc == NULL) {
return Status; }
//
// copy the instance ID string data
//
pTcIfc->InstanceIDLength = IndicationBuffer->InfoBuffer.InstanceIDLength; memcpy(pTcIfc->InstanceID, IndicationBuffer->InfoBuffer.InstanceID, pTcIfc->InstanceIDLength); pTcIfc->InstanceID[pTcIfc->InstanceIDLength/sizeof(WCHAR)] = L'\0';
l = IndicationBufferSize - FIELD_OFFSET(TC_INDICATION_BUFFER,InfoBuffer) - FIELD_OFFSET(TC_SUPPORTED_INFO_BUFFER, AddrListDesc);
AllocMem(&pAddrListDesc, l);
if (pAddrListDesc) {
//
// copy the instance data
// in this case - the network address
//
RtlCopyMemory( pAddrListDesc, &IndicationBuffer->InfoBuffer.AddrListDesc, l );
GetLock( pGlobals->Lock );
FreeMem(pTcIfc->pAddressListDesc);
pTcIfc->AddrListBytesCount = l; pTcIfc->pAddressListDesc = pAddrListDesc;
if (NO_ERROR != GetInterfaceIndex(pTcIfc->pAddressListDesc, &pTcIfc->InterfaceIndex, &pTcIfc->SpecificLinkCtx)) { pTcIfc->InterfaceIndex = IF_UNKNOWN; pTcIfc->SpecificLinkCtx = IF_UNKNOWN;
}
FreeLock( pGlobals->Lock );
#if 0
//
// there's a new addr list, check the GPC client list
//
OpenGpcClients(pTcIfc); #endif
} else {
Status = ERROR_NOT_ENOUGH_MEMORY; }
break;
default: ASSERT(0); }
return Status; }
DWORD CreateClientStruc( IN HANDLE ClRegCtx, OUT PCLIENT_STRUC *ppClient ) { PCLIENT_STRUC pClient; DWORD Status = NO_ERROR;
AllocMem(&pClient, sizeof(CLIENT_STRUC));
if (pClient != NULL) {
RtlZeroMemory(pClient, sizeof(CLIENT_STRUC));
//
// acquire a new handle for the client
//
pClient->ClHandle = AllocateHandle((PVOID)pClient);
if (!pClient->ClHandle) { FreeMem(pClient); return ERROR_NOT_ENOUGH_MEMORY; }
//
// set the other parameters in the client interface
//
pClient->ObjectType = ENUM_CLIENT_TYPE; pClient->ClRegCtx = ClRegCtx; InitializeListHead(&pClient->InterfaceList); ReferenceInit(&pClient->RefCount, pClient, DereferenceClient); REFADD(&pClient->RefCount, 'CLNT');
__try {
InitLock(pClient->Lock); } __except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); IF_DEBUG(ERRORS) { WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status )); } FreeHandle(pClient->ClHandle); FreeMem(pClient); return Status;
}
SET_STATE(pClient->State, INSTALLING);
} else {
Status = ERROR_NOT_ENOUGH_MEMORY; }
*ppClient = pClient;
return Status; }
DWORD CreateClInterfaceStruc( IN HANDLE ClIfcCtx, OUT PINTERFACE_STRUC *ppClIfc ) { PINTERFACE_STRUC pClIfc; DWORD Status = NO_ERROR;
AllocMem(&pClIfc, sizeof(INTERFACE_STRUC));
if (pClIfc != NULL) {
RtlZeroMemory(pClIfc, sizeof(INTERFACE_STRUC));
//
// acquire a new handle for the client
//
GetLock(pGlobals->Lock); pClIfc->ClHandle = AllocateHandle((PVOID)pClIfc); FreeLock(pGlobals->Lock);
if (!pClIfc->ClHandle) { FreeMem(pClIfc); return ERROR_NOT_ENOUGH_MEMORY; }
if ((pClIfc->IfcEvent = CreateEvent( NULL, // pointer to security attributes
TRUE, // flag for manual-reset event
FALSE, // flag for initial state
NULL // pointer to event-object name);
)) == NULL) { Status = GetLastError();
IF_DEBUG(ERRORS) { WSPRINT(( "Error Creating Event for Interface: 0x%X:%d\n", pClIfc, Status)); } FreeHandle(pClIfc->ClHandle); FreeMem(pClIfc); return Status;
}
//
// set the other parameters in the client interface
//
pClIfc->ObjectType = ENUM_INTERFACE_TYPE; pClIfc->ClIfcCtx = ClIfcCtx; pClIfc->CallbackThreadId = 0;
ReferenceInit(&pClIfc->RefCount, pClIfc, DereferenceInterface); REFADD(&pClIfc->RefCount, 'CIFC'); InitializeListHead(&pClIfc->FlowList); __try {
InitLock(pClIfc->Lock);
} __except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
IF_DEBUG(ERRORS) { WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status )); }
CloseHandle(pClIfc->IfcEvent); FreeHandle(pClIfc->ClHandle); FreeMem(pClIfc);
return Status;
}
SET_STATE(pClIfc->State, INSTALLING); pClIfc->Flags = 0; // reset flags
} else { Status = ERROR_NOT_ENOUGH_MEMORY;
}
*ppClIfc = pClIfc;
return Status; }
DWORD CreateKernelInterfaceStruc( OUT PTC_IFC *ppTcIfc, IN DWORD AddressLength ) { PTC_IFC pTcIfc; DWORD Status = NO_ERROR;
IF_DEBUG(CALLS) { WSPRINT(("==> CreateKernelInterfaceStruc: AddressLength %d\n", AddressLength)); }
*ppTcIfc = NULL;
AllocMem(&pTcIfc, sizeof(TC_IFC));
if (pTcIfc) { RtlZeroMemory(pTcIfc, sizeof(TC_IFC));
AllocMem(&pTcIfc->pAddressListDesc, AddressLength);
if (pTcIfc->pAddressListDesc) { RtlZeroMemory(pTcIfc->pAddressListDesc, AddressLength);
//
// initialize the new structure
//
ReferenceInit(&pTcIfc->RefCount, pTcIfc, DereferenceKernelInterface); REFADD(&pTcIfc->RefCount, 'KIFC'); SET_STATE(pTcIfc->State, INSTALLING); __try {
InitLock(pTcIfc->Lock);
} __except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
IF_DEBUG(ERRORS) { WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status )); }
FreeMem(pTcIfc->pAddressListDesc); FreeMem(pTcIfc);
return Status;
}
InitializeListHead(&pTcIfc->ClIfcList); } else {
FreeMem(pTcIfc); Status = ERROR_NOT_ENOUGH_MEMORY; return Status;
} } else { Status = ERROR_NOT_ENOUGH_MEMORY; return Status;
}
*ppTcIfc = pTcIfc;
IF_DEBUG(CALLS) { WSPRINT(("==> CreateKernelInterfaceStruc: Status%d\n", Status)); }
return Status; }
DWORD DereferenceKernelInterface( PTC_IFC pTcIfc ) { DWORD Status = NO_ERROR;
IF_DEBUG(CALLS) { WSPRINT(("==> DereferenceKernelInterfaceStruc: %X\n", pTcIfc)); }
ASSERT(pTcIfc);
ASSERT( IsListEmpty( &pTcIfc->ClIfcList ) );
GetLock( pGlobals->Lock ); RemoveEntryList(&pTcIfc->Linkage); FreeLock( pGlobals->Lock );
DeleteLock(pTcIfc->Lock); FreeMem(pTcIfc->pAddressListDesc); FreeMem(pTcIfc); IF_DEBUG(CALLS) { WSPRINT(("==> DereferenceKernelInterfaceStruc: %d\n", Status)); }
return Status; }
DWORD CreateFlowStruc( IN HANDLE ClFlowCtx, IN PTC_GEN_FLOW pGenFlow, OUT PFLOW_STRUC *ppFlow ) { PFLOW_STRUC pFlow; DWORD Status = NO_ERROR; ULONG l; PUCHAR pCurrentObject; LONG BufRemaining;
*ppFlow = NULL;
__try { pCurrentObject = (PUCHAR) pGenFlow->TcObjects; BufRemaining = pGenFlow->TcObjectsLength;
while ((BufRemaining > 0) && (((QOS_OBJECT_HDR*)pCurrentObject)->ObjectType != QOS_OBJECT_END_OF_LIST))
{ BufRemaining -= ((QOS_OBJECT_HDR*)pCurrentObject)->ObjectLength; pCurrentObject = pCurrentObject + ((QOS_OBJECT_HDR*)pCurrentObject)->ObjectLength; }
if (BufRemaining < 0) return (ERROR_TC_OBJECT_LENGTH_INVALID);
l = FIELD_OFFSET(TC_GEN_FLOW, TcObjects) + pGenFlow->TcObjectsLength;
} __except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode();
IF_DEBUG(ERRORS) { WSPRINT(("CreateFlowStruc: Invalid pGenFlow: = 0x%X\n", Status )); }
return Status; }
AllocMem(&pFlow, sizeof(FLOW_STRUC));
if (pFlow != NULL) {
RtlZeroMemory(pFlow, sizeof(FLOW_STRUC));
//
// acquire a new handle for the flow
//
pFlow->ClHandle = AllocateHandle((PVOID)pFlow); if (!pFlow->ClHandle) { FreeMem(pFlow); return ERROR_NOT_ENOUGH_MEMORY; }
//
// Allocate memory and save the generic flow structure
//
AllocMem(&pFlow->pGenFlow, l);
if (pFlow->pGenFlow == NULL) {
FreeHandle(pFlow->ClHandle); FreeMem(pFlow); pFlow = NULL;
Status = ERROR_NOT_ENOUGH_MEMORY;
} else {
//
// copy the generic flow into the new allocation
//
__try {
RtlCopyMemory(pFlow->pGenFlow, pGenFlow, l);
} __except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); IF_DEBUG(ERRORS) { WSPRINT(("CreateFlowStruc: Exception Error: = 0x%X\n", Status )); } FreeMem(pFlow->pGenFlow); FreeHandle(pFlow->ClHandle); FreeMem(pFlow); return Status; }
//
// set the other parameters in the flow
//
pFlow->GenFlowLen = l; pFlow->ObjectType = ENUM_GEN_FLOW_TYPE; pFlow->ClFlowCtx = ClFlowCtx; pFlow->Flags = 0; pFlow->InstanceNameLength = 0; ReferenceInit(&pFlow->RefCount, pFlow, DereferenceFlow); REFADD(&pFlow->RefCount, 'FLOW'); pFlow->FilterCount = 0; InitializeListHead(&pFlow->FilterList); __try {
InitLock(pFlow->Lock);
} __except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
IF_DEBUG(ERRORS) { WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status )); }
FreeHandle(pFlow->ClHandle); FreeMem(pFlow->pGenFlow); FreeMem(pFlow);
return Status;
}
SET_STATE(pFlow->State, INSTALLING); //
// Next create the event
//
pFlow->PendingEvent = CreateEvent(NULL, // default attr
FALSE, // auto reset
FALSE, // init = not signaled
NULL // no name
);
if (!pFlow->PendingEvent) { // Failed to create event, get the error and free flow
Status = GetLastError(); DeleteFlowStruc( pFlow );
return Status; } } } else {
Status = ERROR_NOT_ENOUGH_MEMORY; }
*ppFlow = pFlow;
return Status; }
DWORD CreateFilterStruc( IN PTC_GEN_FILTER pGenFilter, IN PFLOW_STRUC pFlow, OUT PFILTER_STRUC *ppFilter ) { PFILTER_STRUC pFilter; DWORD Status = NO_ERROR; ULONG GenFilterSize; PTC_GEN_FILTER pGpcFilter; PUCHAR p; ULONG ProtocolId; ULONG PatternSize; PIP_PATTERN pIpPattern; PTC_IFC pTcIfc; int i,n;
*ppFilter = NULL; pTcIfc = pFlow->pInterface->pTcIfc;
ASSERT(pTcIfc);
__try {
switch (pGenFilter->AddressType) {
case NDIS_PROTOCOL_ID_TCP_IP: ProtocolId = GPC_PROTOCOL_TEMPLATE_IP; PatternSize = sizeof(IP_PATTERN); break;
default: return ERROR_INVALID_ADDRESS_TYPE; }
if (PatternSize != pGenFilter->PatternSize || pGenFilter->Pattern == NULL || pGenFilter->Mask == NULL) {
return ERROR_INVALID_PARAMETER; }
} __except(EXCEPTION_EXECUTE_HANDLER) { Status = ERROR_INVALID_PARAMETER; IF_DEBUG(ERRORS) { WSPRINT(("CreateFilterStruc: Exception Error: = 0x%X\n", Status )); } return Status; }
AllocMem(&pFilter, sizeof(FILTER_STRUC));
if (pFilter != NULL) {
RtlZeroMemory(pFilter, sizeof(FILTER_STRUC));
//
// Allocate memory and save the generic filter structure
//
GenFilterSize = sizeof(TC_GEN_FILTER) + 2*pGenFilter->PatternSize; AllocMem(&pGpcFilter, GenFilterSize);
if (pGpcFilter == NULL) {
FreeMem(pFilter); pFilter = NULL;
Status = ERROR_NOT_ENOUGH_MEMORY; } else {
//
// copy the generic filter to local storage
//
pGpcFilter->AddressType = pGenFilter->AddressType; pGpcFilter->PatternSize = PatternSize;
p = (PUCHAR)pGpcFilter + sizeof(TC_GEN_FILTER);
__try {
RtlCopyMemory(p, pGenFilter->Pattern, pGenFilter->PatternSize);
if (pGenFilter->AddressType == NDIS_PROTOCOL_ID_TCP_IP) { if(pTcIfc->InterfaceIndex == IF_UNKNOWN) { if (NO_ERROR != (Status = GetInterfaceIndex(pTcIfc->pAddressListDesc, &pTcIfc->InterfaceIndex, &pTcIfc->SpecificLinkCtx))) { FreeMem(pFilter); FreeMem(pGpcFilter); return Status; } }
//
// IP pattern, set reserved fields
//
pIpPattern = (PIP_PATTERN)p; pIpPattern->Reserved1 = pFlow->pInterface->pTcIfc->InterfaceIndex; pIpPattern->Reserved2 = pFlow->pInterface->pTcIfc->SpecificLinkCtx; pIpPattern->Reserved3[0] = pIpPattern->Reserved3[1] = pIpPattern->Reserved3[2] = 0; } } __except (EXCEPTION_EXECUTE_HANDLER) { Status = ERROR_INVALID_PARAMETER; IF_DEBUG(ERRORS) { WSPRINT(("CreateFilterStruc: Exception Error: = 0x%X\n", Status )); } FreeMem(pGpcFilter); FreeMem(pFilter); return Status; } pGpcFilter->Pattern = (PVOID)p; p += pGenFilter->PatternSize; __try { RtlCopyMemory(p, pGenFilter->Mask, pGenFilter->PatternSize); if (pGenFilter->AddressType == NDIS_PROTOCOL_ID_TCP_IP) { //
// IP pattern, set reserved fields
//
pIpPattern = (PIP_PATTERN)p; pIpPattern->Reserved1 = pIpPattern->Reserved2 = 0xffffffff; pIpPattern->Reserved3[0] = pIpPattern->Reserved3[1] = pIpPattern->Reserved3[2] = 0xff; } } __except (EXCEPTION_EXECUTE_HANDLER) { Status = ERROR_INVALID_PARAMETER; IF_DEBUG(ERRORS) { WSPRINT(("CreateFilterStruc: Exception Error: = 0x%X\n", Status )); } FreeMem(pGpcFilter); FreeMem(pFilter); return Status; }
pGpcFilter->Mask = (PVOID)p; pFilter->pGpcFilter = pGpcFilter;
//
// acquire a new handle for the Filter
//
pFilter->ClHandle = AllocateHandle((PVOID)pFilter);
// what if we're out of memory?
if (!pFilter->ClHandle) { IF_DEBUG(ERRORS) { WSPRINT(("CreateFilterStruc: Cant allocate Handle\n")); }
FreeMem(pGpcFilter); FreeMem(pFilter); return ERROR_NOT_ENOUGH_MEMORY; } //
// set the other parameters in the Filter
//
pFilter->ObjectType = ENUM_FILTER_TYPE; pFilter->Flags = 0;
ReferenceInit(&pFilter->RefCount, pFilter, DereferenceFilter); REFADD(&pFilter->RefCount, 'FILT');
__try {
InitLock(pFilter->Lock);
} __except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
IF_DEBUG(ERRORS) { WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status )); }
FreeHandle(pFilter->ClHandle); FreeMem(pFilter); FreeMem(pGpcFilter);
return Status;
}
SET_STATE(pFilter->State, INSTALLING);
//
// set the Gpc protocol template from the address type
//
pFilter->GpcProtocolTemplate = ProtocolId;
} } else {
Status = ERROR_NOT_ENOUGH_MEMORY; }
*ppFilter = pFilter;
return Status; }
DWORD EnumAllInterfaces(VOID) { PCLIENT_STRUC pClient; DWORD Status; WMIHANDLE WmiHandle; ULONG MyBufferSize = 2 KiloBytes; // is this enough?!?
PWNODE_ALL_DATA pWnode; PWNODE_ALL_DATA pWnodeBuffer; PTC_IFC pTcIfc;
if (_init) return NO_ERROR;
//
// get a WMI block handle to the GUID_QOS_SUPPORTED
//
Status = WmiOpenBlock((GUID *)&GUID_QOS_TC_SUPPORTED, 0, &WmiHandle);
if (ERROR_FAILED(Status)) {
if (Status == ERROR_WMI_GUID_NOT_FOUND) {
//
// this means there is no TC data provider
//
Status = NO_ERROR; //ERROR_TC_NOT_SUPPORTED
}
return Status; }
do {
//
// allocate a private buffer to retrieve all wnodes
//
AllocMem(&pWnodeBuffer, MyBufferSize); if (pWnodeBuffer == NULL) { WmiCloseBlock(WmiHandle); return ERROR_NOT_ENOUGH_MEMORY; }
__try {
Status = WmiQueryAllData(WmiHandle, &MyBufferSize, pWnodeBuffer);
} __except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
IF_DEBUG(ERRORS) { WSPRINT(("EnumAllInterfaces: Exception Error: = %X\n", Status )); }
}
if (Status == ERROR_INSUFFICIENT_BUFFER) {
//
// failed since the buffer was too small
// release the buffer and double the size
//
MyBufferSize *= 2; FreeMem(pWnodeBuffer); pWnodeBuffer = NULL; }
} while (Status == ERROR_INSUFFICIENT_BUFFER);
if (!ERROR_FAILED(Status)) {
ULONG dwInstanceNum; ULONG InstanceSize; PULONG lpdwNameOffsets; BOOL bFixedSize = FALSE; USHORT usNameLength; ULONG DescSize; PTC_SUPPORTED_INFO_BUFFER pTcInfoBuffer;
pWnode = pWnodeBuffer; ASSERT(pWnode->WnodeHeader.Flags & WNODE_FLAG_ALL_DATA); do {
//
// Check for fixed instance size
//
if (pWnode->WnodeHeader.Flags & WNODE_FLAG_FIXED_INSTANCE_SIZE) {
InstanceSize = pWnode->FixedInstanceSize; bFixedSize = TRUE; pTcInfoBuffer = (PTC_SUPPORTED_INFO_BUFFER)OffsetToPtr(pWnode, pWnode->DataBlockOffset); }
//
// Get a pointer to the array of offsets to the instance names
//
lpdwNameOffsets = (PULONG) OffsetToPtr(pWnode, pWnode->OffsetInstanceNameOffsets); for ( dwInstanceNum = 0; dwInstanceNum < pWnode->InstanceCount; dwInstanceNum++) {
usNameLength = *(USHORT *)OffsetToPtr(pWnode, lpdwNameOffsets[dwInstanceNum]); //
// Length and offset for variable data
//
if ( !bFixedSize ) { InstanceSize = pWnode->OffsetInstanceDataAndLength[dwInstanceNum].LengthInstanceData; pTcInfoBuffer = (PTC_SUPPORTED_INFO_BUFFER)OffsetToPtr( (PBYTE)pWnode, pWnode->OffsetInstanceDataAndLength[dwInstanceNum].OffsetInstanceData); } //
// we have all that is needed. we need to figure if
// there is enough buffer space to put the data as well
//
ASSERT(usNameLength < MAX_STRING_LENGTH);
DescSize = InstanceSize - FIELD_OFFSET(TC_SUPPORTED_INFO_BUFFER, AddrListDesc);
//
// Allocate a new interface descriptor structure
//
CreateKernelInterfaceStruc(&pTcIfc, DescSize);
if (pTcIfc != NULL) { //
// copy the instance name string data
//
RtlCopyMemory(pTcIfc->InstanceName, OffsetToPtr(pWnode, lpdwNameOffsets[dwInstanceNum]+2), usNameLength ); pTcIfc->InstanceNameLength = usNameLength; pTcIfc->InstanceName[usNameLength/sizeof(WCHAR)] = (WCHAR)0;
//
// copy the instance ID string data
//
RtlCopyMemory(pTcIfc->InstanceID, &pTcInfoBuffer->InstanceID[0], pTcInfoBuffer->InstanceIDLength ); pTcIfc->InstanceIDLength = pTcInfoBuffer->InstanceIDLength; pTcIfc->InstanceID[pTcInfoBuffer->InstanceIDLength/sizeof(WCHAR)] = (WCHAR)0;
//
// copy the instance data
// in this case - the network address
//
pTcIfc->AddrListBytesCount = DescSize;
//
// a sizeof(ULONG) since the structure is defined as ARRAY
// and the first ULONG is the number of elements
//
RtlCopyMemory( pTcIfc->pAddressListDesc, &pTcInfoBuffer->AddrListDesc, DescSize );
if (NO_ERROR != GetInterfaceIndex(pTcIfc->pAddressListDesc, &pTcIfc->InterfaceIndex, &pTcIfc->SpecificLinkCtx)) { pTcIfc->InterfaceIndex = IF_UNKNOWN; pTcIfc->SpecificLinkCtx = IF_UNKNOWN;
}
// set the state to open
GetLock(pTcIfc->Lock); SET_STATE(pTcIfc->State, OPEN); FreeLock(pTcIfc->Lock);
//
// Add the structure to the global linked list
//
GetLock( pGlobals->Lock ); InsertTailList(&pGlobals->TcIfcList, &pTcIfc->Linkage ); FreeLock( pGlobals->Lock );
#if 0
//
// make sure we have one gpc client per address type
//
Status = OpenGpcClients(pTcIfc); if (ERROR_FAILED(Status)) {
break; } #endif
} else {
//
// no more memory, quit here
//
Status = ERROR_NOT_ENOUGH_MEMORY; break; } } //
// Update Wnode to point to next node
//
if ( pWnode->WnodeHeader.Linkage != 0) {
pWnode = (PWNODE_ALL_DATA) OffsetToPtr( pWnode, pWnode->WnodeHeader.Linkage); } else { pWnode = NULL; }
} while (pWnode != NULL && !ERROR_FAILED(Status));
}
//
// release resources and close WMI handle
//
WmiCloseBlock(WmiHandle);
if (pWnodeBuffer) FreeMem(pWnodeBuffer);
if (Status == NO_ERROR) {
_init = TRUE; }
return Status; }
DWORD CloseInterface( IN PINTERFACE_STRUC pInterface, BOOLEAN RemoveFlows ) { IF_DEBUG(CALLS) { WSPRINT(("==>CloseInterface: pInterface=%X\n", pInterface)); }
if (RemoveFlows) {
CloseOpenFlows(pInterface); }
REFDEL(&pInterface->RefCount, 'CIFC');
IF_DEBUG(CALLS) { WSPRINT(("==>CloseInterface: NO_ERROR\n")); }
return NO_ERROR; }
DWORD DeleteFlow( IN PFLOW_STRUC pFlow, IN BOOLEAN RemoveFilters ) { DWORD Status; PLIST_ENTRY pEntry; PFILTER_STRUC pFilter;
IF_DEBUG(CALLS) { WSPRINT(("DeleteFlow: attempting to delete flow=0x%X\n", PtrToUlong(pFlow))); }
if (RemoveFilters) {
CloseOpenFilters(pFlow); } else {
if (/*pFlow->FilterCount > 0*/ !IsListEmpty(&pFlow->FilterList)) {
IF_DEBUG(ERRORS) { WSPRINT(("DeleteFlow: filter list NOT empty\n")); }
#if DBG
pEntry = pFlow->FilterList.Flink; while (pEntry != &pFlow->FilterList) {
pFilter = CONTAINING_RECORD(pEntry, FILTER_STRUC, Linkage); IF_DEBUG(ERRORS) { WSPRINT(("<==TcDeleteFlow: Filter %x (handle %x) is open with RefCount:%d\n", pFilter, pFilter->ClHandle, pFilter->RefCount)); }
pEntry = pEntry->Flink; } #endif
return ERROR_TC_SUPPORTED_OBJECTS_EXIST; } }
//
// can remove the flow now
//
Status = IoDeleteFlow( pFlow, (BOOLEAN)!RemoveFilters );
IF_DEBUG(CALLS) { WSPRINT(("DeleteFlow: IoDeleteFlow returned=0x%X\n", Status)); }
if (!ERROR_PENDING(Status)) {
//
// call completed, either success or failure...
//
CompleteDeleteFlow(pFlow, Status); }
return Status; }
DWORD DeleteFilter( IN PFILTER_STRUC pFilter ) { DWORD Status;
IF_DEBUG(CALLS) { WSPRINT(( "DeleteFilter: attempting to delete=0x%X\n", PtrToUlong(pFilter))); } //
// call to actually delete the filter
//
Status = IoDeleteFilter( pFilter );
IF_DEBUG(CALLS) { WSPRINT(( "DeleteFilter: IoDeleteFilter returned=0x%X\n", Status)); }
//ASSERT(Status == NO_ERROR);
REFDEL(&pFilter->RefCount, 'FILT');
return Status; }
PGPC_CLIENT FindGpcClient( IN ULONG CfInfoType ) { PGPC_CLIENT pGpcClient = NULL; PLIST_ENTRY pHead, pEntry;
GetLock( pGlobals->Lock );
pHead = &pGlobals->GpcClientList; pEntry = pHead->Flink;
while (pHead != pEntry && pGpcClient == NULL) {
pGpcClient = CONTAINING_RECORD(pEntry, GPC_CLIENT, Linkage); if (CfInfoType != pGpcClient->CfInfoType) {
//
// address type doesn't match!
//
pGpcClient = NULL; } pEntry = pEntry->Flink; }
FreeLock( pGlobals->Lock );
return pGpcClient; }
VOID CompleteAddFlow( IN PFLOW_STRUC pFlow, IN DWORD Status ) { PINTERFACE_STRUC pInterface;
ASSERT(pFlow); ASSERT(!ERROR_PENDING(Status));
IF_DEBUG(CALLS) { WSPRINT(("CompleteAddFlow: pFlow=0x%X Status=0x%X\n", PtrToUlong(pFlow), Status)); }
if(pFlow->CompletionBuffer) {
FreeMem(pFlow->CompletionBuffer); pFlow->CompletionBuffer = NULL;
}
//
// Check if the interface is still around.
//
GetLock(pFlow->Lock); pInterface = pFlow->pInterface; FreeLock(pFlow->Lock);
if (ERROR_FAILED(Status)) { //
// failed, release resources
//
CompleteDeleteFlow(pFlow, Status); } else { GetLock(pGlobals->Lock); GetLock(pInterface->Lock);
if (QUERY_STATE(pInterface->State) != OPEN) { FreeLock(pInterface->Lock); FreeLock(pGlobals->Lock);
IF_DEBUG(ERRORS) { WSPRINT(("CompleteAddFlow: Interface (%X) is NOT open pFlow=0x%X Status=0x%X\n", pInterface->ClHandle, PtrToUlong(pFlow), Status)); }
//
// Delete the only ref we have on this flow and get out.
//
REFDEL(&pFlow->RefCount, 'FLOW');
} else {
FreeLock(pInterface->Lock);
//
// The flow is ready for business
//
GetLock(pFlow->Lock); SET_STATE(pFlow->State, OPEN); FreeLock(pFlow->Lock); //
// Announce on the lists that we are ready for business
//
pInterface->FlowCount++; REFADD(&pInterface->RefCount, 'FLOW'); InsertTailList(&pInterface->FlowList, &pFlow->Linkage); FreeLock(pGlobals->Lock);
}
}
//
// This ref was taken in TcAddFlow.
//
REFDEL(&pInterface->RefCount, 'TCAF');
}
VOID CompleteModifyFlow( IN PFLOW_STRUC pFlow, IN DWORD Status ) { ASSERT(pFlow); ASSERT(!ERROR_PENDING(Status));
IF_DEBUG(CALLS) { WSPRINT(("CompleteModifyFlow: pFlow=0x%X Status=0x%X\n", PtrToUlong(pFlow), Status)); }
GetLock(pFlow->Lock);
if(pFlow->CompletionBuffer) {
FreeMem(pFlow->CompletionBuffer); pFlow->CompletionBuffer = NULL;
}
if (ERROR_FAILED(Status)) {
//
// failed, release the newly allocated generic flow parameters
//
FreeMem(pFlow->pGenFlow1);
} else {
//
// modification accepted, update the generic flow parameters
//
FreeMem(pFlow->pGenFlow); pFlow->pGenFlow = pFlow->pGenFlow1; pFlow->GenFlowLen = pFlow->GenFlowLen;
}
//
// clear the installing flag
//
pFlow->Flags &= ~TC_FLAGS_MODIFYING; pFlow->pGenFlow1 = NULL; pFlow->GenFlowLen1 = 0;
FreeLock(pFlow->Lock);
//
// This ref was taken in TcModifyFlow
//
REFDEL(&pFlow->RefCount, 'TCMF'); IF_DEBUG(CALLS) { WSPRINT(("CompleteModifyFlow: pFlow=0x%X Status=0x%X\n", PtrToUlong(pFlow), Status)); }
}
VOID CompleteDeleteFlow( IN PFLOW_STRUC pFlow, IN DWORD Status ) { ASSERT(pFlow); //ASSERT(Status == NO_ERROR);
//ASSERT(pFlow->CompletionBuffer);
IF_DEBUG(CALLS) { WSPRINT(("CompleteDeleteFlow: pFlow=0x%X Status=0x%X\n", PtrToUlong(pFlow), Status)); }
//
// okay, release resources
//
GetLock(pFlow->Lock); if (pFlow->CompletionBuffer) { FreeMem(pFlow->CompletionBuffer); pFlow->CompletionBuffer = NULL; } FreeLock(pFlow->Lock); IF_DEBUG(REFCOUNTS) { WSPRINT(("#21 DEREF FLOW %X (%X) ref(%d)\n", pFlow->ClHandle, pFlow, pFlow->RefCount)); }
REFDEL(&pFlow->RefCount, 'FLOW');
}
DWORD OpenGpcClients( IN ULONG CfInfoType ) { DWORD Status = NO_ERROR; PLIST_ENTRY pHead, pEntry; PGPC_CLIENT pGpcClient; //int i;
if (FindGpcClient(CfInfoType) == NULL) { //
// create an entry in the
//
AllocMem(&pGpcClient, sizeof(GPC_CLIENT) ); if (pGpcClient == NULL) { return ERROR_NOT_ENOUGH_MEMORY; } pGpcClient->CfInfoType = CfInfoType; pGpcClient->RefCount = 1; //
// register the gpc client
//
Status = IoRegisterClient(pGpcClient); if (ERROR_FAILED(Status)) { FreeMem(pGpcClient);
} else { GetLock( pGlobals->Lock); InsertTailList(&pGlobals->GpcClientList, &pGpcClient->Linkage); FreeLock( pGlobals->Lock); } } return Status; }
DWORD DereferenceInterface( IN PINTERFACE_STRUC pInterface ) {
DWORD Status = NO_ERROR;
IF_DEBUG(CALLS) { WSPRINT(("==>DereferenceInterface: IfcH=%X RefCount=%d\n", pInterface->ClHandle, pInterface->RefCount)); } FreeHandle(pInterface->ClHandle); //GetLock(pGlobals->Lock);
IF_DEBUG(REFCOUNTS) { WSPRINT(("==>DereferenceInterface: IfcH=%X Interface=%x\n", pInterface->ClHandle, pInterface));
} //
// close the interface and all flows/filters
//
RemoveEntryList(&pInterface->Linkage); RemoveEntryList(&pInterface->NextIfc);
//
// Deregister from any guid notification requests
//
TcipDeleteInterfaceFromNotificationList( pInterface, 0 );
//
// #295267
// Do not dereference Client OR decrement Interface Count until
// the Interface is actually going away. Otherwise, the client structures
// are cleaned out, and when the ref count finally goes down and we
// touch this code path, we hit an AV.
//
pInterface->pClient->InterfaceCount--; IF_DEBUG(HANDLES) { WSPRINT(("DEREF Client A : %x\n", pInterface->pClient->ClHandle)); }
REFDEL(&pInterface->pClient->RefCount, 'CIFC'); REFDEL(&pInterface->pTcIfc->RefCount, 'CIFC'); //
// This is complex, so read carefully.
// We want CloseInterface to wait until the event is set (292120).
// It is likely that in case the TcCloseInterface call didn't
// come in, we dont have to set the Event since the TC_FLAGS_WAITING
// will not be set in that case.
//
if (!IS_WAITING(pInterface->Flags)) { CloseHandle(pInterface->IfcEvent);
} else {
SetEvent(pInterface->IfcEvent);
}
//
// free the interface resources
//
DeleteLock(pInterface->Lock); FreeMem(pInterface); //FreeLock(pGlobals->Lock);
IF_DEBUG(CALLS) { WSPRINT(("<==DereferenceInterface: Status=%X\n", Status)); }
return Status; }
DWORD DereferenceFlow( IN PFLOW_STRUC pFlow ) { DWORD Status = NO_ERROR;
IF_DEBUG(CALLS) { WSPRINT(("==>DereferenceFlow: FlowH=%X Flow=%X\n", pFlow->ClHandle, pFlow)); }
//GetLock(pGlobals->Lock);
IF_DEBUG(REFCOUNTS) { WSPRINT(("==>DereferenceFlow: FlowH=%X Flow=%X\n", pFlow->ClHandle, pFlow)); }
FreeHandle(pFlow->ClHandle);
GetLock(pFlow->Lock); if (QUERY_STATE(pFlow->State) != INSTALLING) { FreeLock(pFlow->Lock); RemoveEntryList(&pFlow->Linkage); pFlow->pInterface->FlowCount--; IF_DEBUG(HANDLES) { WSPRINT(("DEREF Interface A : %x\n", pFlow->pInterface->ClHandle)); }
REFDEL(&pFlow->pInterface->RefCount, 'FLOW');
} else { FreeLock(pFlow->Lock);
}
//
// moved here from CompleteDeleteFlow
//
//
// free the interface resources
//
DeleteFlowStruc(pFlow); //FreeLock(pGlobals->Lock);
IF_DEBUG(CALLS) { WSPRINT(("<==DereferenceFlow: Status=%X\n", Status)); }
return Status; }
DWORD DereferenceClient( IN PCLIENT_STRUC pClient ) { //GetLock( pGlobals->Lock );
IF_DEBUG(REFCOUNTS) { WSPRINT(("==>DereferenceClient: pClient=%x, Handle=%x, RefCount=%d\n", pClient, pClient->ClHandle, pClient->RefCount)); }
GetLock(pClient->Lock); SET_STATE(pClient->State, REMOVED); FreeLock(pClient->Lock);
FreeHandle( pClient->ClHandle ); RemoveEntryList( &pClient->Linkage ); DeleteLock(pClient->Lock); FreeMem( pClient );
//FreeLock( pGlobals->Lock );
return NO_ERROR; }
DWORD DereferenceFilter( IN PFILTER_STRUC pFilter ) { DWORD Status = NO_ERROR;
IF_DEBUG(CALLS) { WSPRINT(("==>DereferenceFilter: FilterH=%X RefCount=%d\n", pFilter->ClHandle, pFilter->RefCount)); }
//GetLock(pGlobals->Lock);
IF_DEBUG(REFCOUNTS) { WSPRINT(("==>DereferenceFilter: FilterH=%X Filter=%X on FLOW=%X\n", pFilter->ClHandle, pFilter, pFilter->pFlow)); } FreeHandle(pFilter->ClHandle); //
// remove the flow from the list
//
GetLock(pFilter->Lock); if (QUERY_STATE(pFilter->State) != INSTALLING) { FreeLock(pFilter->Lock); RemoveEntryList(&pFilter->Linkage); pFilter->pFlow->FilterCount--;
IF_DEBUG(REFCOUNTS) { WSPRINT(("#22 DEREF FLOW %X (%X) ref(%d)\n", pFilter->pFlow->ClHandle, pFilter->pFlow, pFilter->pFlow->RefCount)); }
REFDEL(&pFilter->pFlow->RefCount, 'FILT');
} else { FreeLock(pFilter->Lock);
}
DeleteFilterStruc(pFilter); //FreeLock(pGlobals->Lock);
IF_DEBUG(CALLS) { WSPRINT(("<==DereferenceFilter: Status=%X\n", Status)); }
return Status; }
DWORD GetInterfaceIndex( IN PADDRESS_LIST_DESCRIPTOR pAddressListDesc, OUT PULONG pInterfaceIndex, OUT PULONG pSpecificLinkCtx) { PNETWORK_ADDRESS_LIST pAddrList; NETWORK_ADDRESS UNALIGNED *pAddr; DWORD n,k; DWORD Status = NO_ERROR; PMIB_IPADDRTABLE pIpAddrTbl; DWORD dwSize = 2 KiloBytes; NETWORK_ADDRESS_IP UNALIGNED *pIpNetAddr = 0; DWORD cAddr;
*pInterfaceIndex = 0; *pSpecificLinkCtx = 0;
cAddr = pAddressListDesc->AddressList.AddressCount; if (cAddr == 0) {
//
// no address
//
return NO_ERROR; }
#if INTERFACE_ID
AllocMem(&pIpAddrTbl, dwSize);
if (pIpAddrTbl == NULL) { return ERROR_NOT_ENOUGH_MEMORY; }
pAddr = (UNALIGNED NETWORK_ADDRESS *) &pAddressListDesc->AddressList.Address[0]; for (n = 0; n < cAddr; n++) { if (pAddr->AddressType == NDIS_PROTOCOL_ID_TCP_IP) { pIpNetAddr = (UNALIGNED NETWORK_ADDRESS_IP *)&pAddr->Address[0]; break; } pAddr = (UNALIGNED NETWORK_ADDRESS *)(((PUCHAR)pAddr) + pAddr->AddressLength + FIELD_OFFSET(NETWORK_ADDRESS, Address)); }
if (pIpNetAddr) {
Status = GetIpAddrTableFromStack( pIpAddrTbl, dwSize, FALSE ); if (Status == NO_ERROR) { //
// search for the matching IP address to IpAddr
// in the table we got back from the stack
//
for (k = 0; k < pIpAddrTbl->dwNumEntries; k++) {
if (pIpAddrTbl->table[k].dwAddr == pIpNetAddr->in_addr) {
//
// found one, get the index
//
*pInterfaceIndex = pIpAddrTbl->table[k].dwIndex; break; } }
if (pAddressListDesc->MediaType == NdisMediumWan) { if (n+1 < cAddr) {
//
// there is another address that contains
// the remote client address
// this should be used as the link ID
//
pAddr = (UNALIGNED NETWORK_ADDRESS *)(((PUCHAR)pAddr) + pAddr->AddressLength + FIELD_OFFSET(NETWORK_ADDRESS, Address)); if (pAddr->AddressType == NDIS_PROTOCOL_ID_TCP_IP) { //
// parse the second IP address,
// this would be the remote IP address for dialin WAN
//
pIpNetAddr = (UNALIGNED NETWORK_ADDRESS_IP *)&pAddr->Address[0]; *pSpecificLinkCtx = pIpNetAddr->in_addr; } } } } }
FreeMem(pIpAddrTbl);
#endif
return Status; }
|