Platform SDK: Quality of Service |
The ENUMERATION_BUFFER structure contains information specific to a given flow, including flow name, the number of filters associated with the flow, and an array of filters associated with the flow.
typedef struct _ENUMERATION_BUFFER { ULONG Length; ULONG OwnerProcessId; USHORT FlowNameLength; WCHAR FlowName[MAX_STRING_LENGTH]; PTC_GEN_FLOW pFlow; ULONG NumberOfFilters; TC_GEN_FILTER GenericFilter[1]; } ENUMERATION_BUFFER, *PENUMERATION_BUFFER;
sizeof(TC_GEN_FILTER) + 2 * [the pattern size of the current TC_GEN_FILTER structure].
The following example shows how to use the ENUMERATION_BUFFER with traffic control. It also provides an example of enumerating through the array of TC_GEN_FILTER structures found in GenericFilter.
#define UNICODE #include <winsock2.h> #include <windows.h> #include <qos.h> #include <ntddndis.h> #include <traffic.h> #include <tcerror.h> #include <stdlib.h> #include <stdio.h> #define INITIAL_IFC_BUFFER_SIZE 4096 #define INITIAL_FLOW_BUFFER_SIZE 1024 #define FLOW_NAME_BUFFER_SIZE 1024 #define QUERY_FLOW_BUFFER_SIZE 2048 #define QUERY_IFC_BUFFER_SIZE 2048 void ExamineFlow(int nFlow, PENUMERATION_BUFFER pEnumBuffer) { PTC_GEN_FILTER pCurrentFilter = pEnumBuffer->GenericFilter; printf(" Flow %d:\n",nFlow); printf(" Name: %ws\n",pEnumBuffer->FlowName); printf(" OwnerProcessID: %d\n",pEnumBuffer->OwnerProcessId); printf(" Number of Filters: %d\n",pEnumBuffer->NumberOfFilters); for (ULONG i=0; i < pEnumBuffer->NumberOfFilters; i++) { printf(" Filter %d: ",i); if (pCurrentFilter->AddressType == NDIS_PROTOCOL_ID_TCP_IP) printf("TCP/IP Filter\n"); else if (pCurrentFilter->AddressType == NDIS_PROTOCOL_ID_IPX) printf("IPX Filter\n"); else printf("Other Filter Type\n"); pCurrentFilter = (PTC_GEN_FILTER)((PBYTE)pCurrentFilter + sizeof(TC_GEN_FILTER) + (pCurrentFilter->PatternSize * 2)); } } void EnumFlows(HANDLE hIfc) { PENUMERATION_BUFFER pEnumBuffer, pCurrentEnumBuffer; ULONG EnumBufferSize = INITIAL_FLOW_BUFFER_SIZE; ULONG FilledEnumBufferSize; HANDLE hEnum; ULONG FlowCount, err, i; int nFlow = 0; pEnumBuffer = (PENUMERATION_BUFFER) malloc ( EnumBufferSize ); if (pEnumBuffer == NULL) { printf("Error: malloc"); return; } hEnum = NULL; do { FilledEnumBufferSize = EnumBufferSize; FlowCount = -1; // Request All Flows err = TcEnumerateFlows ( hIfc, &hEnum, &FlowCount, &FilledEnumBufferSize, pEnumBuffer ); if (err == ERROR_INSUFFICIENT_BUFFER) { // // The buffer was not large enough to hold any entries. Make it bigger. // EnumBufferSize *= 2; pEnumBuffer = (PENUMERATION_BUFFER) realloc( pEnumBuffer, EnumBufferSize ); } else if (err == NO_ERROR) { pCurrentEnumBuffer = pEnumBuffer; for (ULONG i = 0; i < FlowCount; i++) { nFlow++; ExamineFlow(nFlow, pCurrentEnumBuffer); // // Advance to the next buffer // pCurrentEnumBuffer = (PENUMERATION_BUFFER)((PBYTE)pCurrentEnumBuffer + pCurrentEnumBuffer->Length); } } } while ( (hEnum != NULL && err == NO_ERROR) || (err == ERROR_INSUFFICIENT_BUFFER) ); free(pEnumBuffer); if (err != NO_ERROR && err != ERROR_INVALID_DATA) { printf("Error: TcEnumerateFlow"); return; } } void ExamineInterface(HANDLE hClient, int nIfcs, PTC_IFC_DESCRIPTOR pCurrentIfc) { HANDLE hIfc; ULONG err; printf("Interface %d:\n Name: %ws\n\n",nIfcs,pCurrentIfc->pInterfaceName); err = TcOpenInterface( pCurrentIfc->pInterfaceName, hClient, NULL, &hIfc); if (err != NO_ERROR) { printf("Error: TcOpenInterface"); return; } EnumFlows(hIfc); err = TcCloseInterface(hIfc); if (err != NO_ERROR) { printf("Error: TcCloseInterface"); return; } } void EnumInterfaces(HANDLE hClient) { PTC_IFC_DESCRIPTOR pIfcs,pCurrentIfc; ULONG BufferSize = INITIAL_IFC_BUFFER_SIZE; ULONG ActualBufferSize, RemainingBufferSize; int nIfcs = 0; while (true) { pIfcs = (PTC_IFC_DESCRIPTOR) malloc(BufferSize); if (pIfcs == NULL) { printf("Error: malloc"); return; } ULONG err = TcEnumerateInterfaces( hClient, &ActualBufferSize, pIfcs); if (err == NO_ERROR) { // We've got the data break; } else if (err == ERROR_INSUFFICIENT_BUFFER) { free(pIfcs); BufferSize *= 2; } else { printf("Error: TcEnumerateInterfaces"); return; } } RemainingBufferSize = ActualBufferSize; pCurrentIfc = pIfcs; while (RemainingBufferSize > 0) { nIfcs++; ExamineInterface(hClient, nIfcs, pCurrentIfc); RemainingBufferSize -= pCurrentIfc->Length; pCurrentIfc = (PTC_IFC_DESCRIPTOR) ((PBYTE) pCurrentIfc + pCurrentIfc->Length); } free(pIfcs); } VOID CALLBACK NotifyHandler( HANDLE ClRegCtx, HANDLE ClIfcCtx, ULONG Event, ULONG SubCode, ULONG BufSize, PVOID Buffer) { switch (Event) { case TC_NOTIFY_IFC_UP: case TC_NOTIFY_IFC_CLOSE: case TC_NOTIFY_IFC_CHANGE: case TC_NOTIFY_PARAM_CHANGED: case TC_NOTIFY_FLOW_CLOSE: break; } } void main() { ULONG err; TCI_CLIENT_FUNC_LIST Handlers; HANDLE hClient; Handlers.ClNotifyHandler = NotifyHandler; Handlers.ClAddFlowCompleteHandler = NULL; Handlers.ClModifyFlowCompleteHandler = NULL; Handlers.ClDeleteFlowCompleteHandler = NULL; err = TcRegisterClient(CURRENT_TCI_VERSION, (HANDLE) NULL, &Handlers, &hClient); if (err != NO_ERROR) { printf("Error: TcRegisterClient"); exit(1); } EnumInterfaces(hClient); err = TcDeregisterClient(hClient); if (err != NO_ERROR) { printf("Error: TcDeregisterClient"); exit(1); } }
Windows NT/2000: Requires Windows 2000.
Windows 95/98: Unsupported.
Header: Declared in Traffic.h.