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.
2408 lines
59 KiB
2408 lines
59 KiB
/*++
|
|
|
|
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;
|
|
}
|
|
|
|
|