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.
1597 lines
42 KiB
1597 lines
42 KiB
/*********************************************************************/
|
|
/** Microsoft Generic Packet Scheduler **/
|
|
/** Copyright(c) Microsoft Corp., 1996-1997 **/
|
|
/********************************************************************/
|
|
|
|
#ifndef __GPCDEF
|
|
#define __GPCDEF
|
|
|
|
//*** gpcdef.h - GPC internal definitions & prototypes
|
|
//
|
|
// This file containes all the GPC data structures & defines
|
|
|
|
|
|
/*
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// defines
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
*/
|
|
|
|
//
|
|
// Max number of clients per blob (same CF)
|
|
//
|
|
// AbhisheV - This can not be more than sizeof(ULONG)*8.
|
|
//
|
|
|
|
#define MAX_CLIENTS_CTX_PER_BLOB 32
|
|
|
|
|
|
//
|
|
// Max pattern size,
|
|
// GPC_IP_PATTERN = 24 bytes
|
|
// GPC_IPX_PATTERN = 24 bytes
|
|
//
|
|
#define MAX_PATTERN_SIZE sizeof(GPC_IP_PATTERN)
|
|
|
|
extern BOOLEAN IsItChanging;
|
|
|
|
//
|
|
// Pattern flags
|
|
//
|
|
#define PATTERN_SPECIFIC 0x00000001
|
|
#define PATTERN_AUTO 0x00000002
|
|
#define PATTERN_REMOVE_CB_BLOB 0x00000004
|
|
// Following flag to be set and unset only in addspecificpatternwithtimer.
|
|
// It indicates pattern has been created but not on timer list yet.
|
|
// It is set before inserting it into the hash table i.e calling
|
|
// AddSpecificPattern.
|
|
// It is supposed to be reset after putting pattern on timer list
|
|
// which in turn should occur after the pattern has been added into
|
|
// the hash table i.e. a successful call to addspecificpattern
|
|
#define PATTERN_AUTO_NOT_READY 0x00000008
|
|
|
|
//
|
|
// Auto Pattern defines
|
|
//
|
|
|
|
// Every PATTERN_TIMEOUT seconds, the PatternTimerExpiry Routine gets called.
|
|
#define PATTERN_TIMEOUT 60000 // 60 seconds
|
|
|
|
// This is the amount of time that a Pattern created for optimization
|
|
// lives on the Pattern List.
|
|
#define AUTO_PATTERN_ENTRY_TIMEOUT 300000 // 5 minutes
|
|
|
|
// This is the number of timer granularity.
|
|
#define NUMBER_OF_WHEELS (AUTO_PATTERN_ENTRY_TIMEOUT/PATTERN_TIMEOUT)
|
|
|
|
//
|
|
// The size of structure to be allocated for TCP query with 1 address
|
|
#define ROUTING_INFO_ADDR_1_SIZE \
|
|
FIELD_OFFSET(GPC_TCP_QUERY_CONTEXT ,RouteInfo) + \
|
|
FIELD_OFFSET(TDI_ROUTING_INFO, Address) + \
|
|
FIELD_OFFSET(TRANSPORT_ADDRESS, Address) + \
|
|
FIELD_OFFSET(TA_ADDRESS, Address) + sizeof(TDI_ADDRESS_IP)
|
|
|
|
//
|
|
// For 2 addresses
|
|
#define ROUTING_INFO_ADDR_2_SIZE ROUTING_INFO_ADDR_1_SIZE + \
|
|
FIELD_OFFSET(TA_ADDRESS, Address) + sizeof(TDI_ADDRESS_IP)
|
|
|
|
|
|
|
|
// New debug locks [ShreeM]
|
|
// This will enable us to figure out who took the lock last
|
|
// and who released it last. New structure defined below and
|
|
// lock_acquire and lock_release macros are redefined later.
|
|
|
|
typedef struct _GPC_LOCK {
|
|
|
|
NDIS_SPIN_LOCK Lock;
|
|
|
|
#if DBG
|
|
PETHREAD CurrentThread;
|
|
KIRQL CurrentIRQL;
|
|
LONG LockAcquired; // is it current held?
|
|
UCHAR LastAcquireFile[8];
|
|
ULONG LastAcquireLine;
|
|
UCHAR LastReleaseFile[8];
|
|
ULONG LastReleaseLine;
|
|
#endif
|
|
|
|
} GPC_LOCK, PGPC_LOCK;
|
|
|
|
//
|
|
//
|
|
// states for blobs, patterns and more
|
|
//
|
|
typedef enum {
|
|
|
|
GPC_STATE_READY = 0,
|
|
GPC_STATE_INIT,
|
|
GPC_STATE_ADD,
|
|
GPC_STATE_MODIFY,
|
|
GPC_STATE_REMOVE,
|
|
GPC_STATE_FORCE_REMOVE,
|
|
GPC_STATE_DELETE,
|
|
GPC_STATE_INVALID,
|
|
GPC_STATE_NOTREADY,
|
|
GPC_STATE_ERROR,
|
|
GPC_STATE_PENDING
|
|
|
|
} GPC_STATE;
|
|
|
|
|
|
//
|
|
// ObjectVerification macro
|
|
//
|
|
#define VERIFY_OBJECT(_obj, _val) if(_obj) \
|
|
{if(*(GPC_ENUM_OBJECT_TYPE *)_obj!=_val) return STATUS_INVALID_HANDLE;}
|
|
//Use this macro when you want to catch the error and not directly
|
|
//return from the function
|
|
#define VERIFY_OBJECT_WITH_STATUS(_obj, _val,__status) if(_obj) \
|
|
{if(*(GPC_ENUM_OBJECT_TYPE *)_obj!=_val) __status = STATUS_INVALID_HANDLE;}
|
|
|
|
|
|
//
|
|
// define event log error codes
|
|
//
|
|
#define GPC_ERROR_INIT_MAIN 0x00010000
|
|
#define GPC_ERROR_INIT_IOCTL 0x00020000
|
|
|
|
|
|
#define GPC_FLAGS_USERMODE_CLIENT 0x80000000
|
|
|
|
#define IS_USERMODE_CLIENT(_pc) \
|
|
TEST_BIT_ON((_pc)->Flags,GPC_FLAGS_USERMODE_CLIENT)
|
|
|
|
#define IS_USERMODE_CLIENT_EX(_pc) \
|
|
TEST_BIT_ON((_pc)->Flags,GPC_FLAGS_USERMODE_CLIENT_EX)
|
|
|
|
|
|
//
|
|
// for ioctl
|
|
//
|
|
#define SHUTDOWN_DELETE_DEVICE 0x00000100
|
|
#define SHUTDOWN_DELETE_SYMLINK 0x00000200
|
|
|
|
//
|
|
// helper macros
|
|
//
|
|
#define TEST_BIT_ON(_v,_b) (((_v)&(_b))==(_b))
|
|
#define TEST_BIT_OFF(_v,_b) (((_v)&(_b))==0)
|
|
|
|
|
|
|
|
//
|
|
// Define Default AutoPatternLimits
|
|
//
|
|
|
|
#define DEFAULT_SMALL_SYSTEM_AUTO_PATTERN_LIMIT 2000
|
|
#define DEFAULT_MEDIUM_SYSTEM_AUTO_PATTERN_LIMIT 8000
|
|
#define DEFAULT_LARGE_SYSTEM_AUTO_PATTERN_LIMIT 12000
|
|
|
|
//
|
|
// Define Registry settings to read into
|
|
//
|
|
#define GPC_REG_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\GPC"
|
|
|
|
//
|
|
// Work Buffer size for reading from the registry
|
|
//
|
|
#define WORK_BUFFER_SIZE 256
|
|
|
|
//
|
|
// Reg Key under which the limit on the number of autopatterns is stored
|
|
//
|
|
#define GPC_REG_AUTO_PATTERN_LIMIT L"AutoPatternLimit"
|
|
#define GPC_AUTO_PATTERN_MIN 2000
|
|
#define GPC_AUTO_PATTERN_MAX 20000
|
|
|
|
#if DBG
|
|
|
|
#define NDIS_INIT_LOCK(_sl) {\
|
|
NdisAllocateSpinLock(&(_sl)->Lock); \
|
|
TRACE(LOCKS,(_sl),(_sl)->Lock.OldIrql,"LOCK");\
|
|
(_sl)->LockAcquired = -1; \
|
|
strncpy((_sl)->LastAcquireFile, strrchr(__FILE__,'\\')+1, 7); \
|
|
(_sl)->LastAcquireLine = __LINE__; \
|
|
strncpy((_sl)->LastReleaseFile, strrchr(__FILE__,'\\')+1, 7); \
|
|
(_sl)->LastReleaseLine = __LINE__; \
|
|
(_sl)->CurrentIRQL = KeGetCurrentIrql(); \
|
|
(_sl)->CurrentThread = PsGetCurrentThread(); \
|
|
}
|
|
|
|
#define NDIS_LOCK(_sl) {\
|
|
NdisAcquireSpinLock(&(_sl)->Lock);\
|
|
TRACE(LOCKS,(_sl),(_sl)->Lock.OldIrql,"LOCK");\
|
|
(_sl)->LockAcquired = TRUE; \
|
|
strncpy((_sl)->LastAcquireFile, strrchr(__FILE__,'\\')+1, 7); \
|
|
(_sl)->LastAcquireLine = __LINE__; \
|
|
(_sl)->CurrentIRQL = KeGetCurrentIrql(); \
|
|
(_sl)->CurrentThread = PsGetCurrentThread(); \
|
|
}
|
|
|
|
#define NDIS_UNLOCK(_sl) {\
|
|
(_sl)->LockAcquired = FALSE; \
|
|
strncpy((_sl)->LastReleaseFile, strrchr(__FILE__,'\\')+1, 7); \
|
|
(_sl)->LastReleaseLine = __LINE__; \
|
|
TRACE(LOCKS,(_sl),(_sl)->Lock.OldIrql,"UNLOCK");\
|
|
NdisReleaseSpinLock(&(_sl)->Lock);\
|
|
}
|
|
|
|
#define NDIS_DPR_LOCK(_sl) {\
|
|
NdisDprAcquireSpinLock(&(_sl)->Lock);\
|
|
TRACE(LOCKS,(_sl),(_sl)->Lock.OldIrql,"DPR_LOCK");\
|
|
(_sl)->LockAcquired = TRUE; \
|
|
strncpy((_sl)->LastAcquireFile, strrchr(__FILE__,'\\')+1, 7); \
|
|
(_sl)->LastAcquireLine = __LINE__; \
|
|
(_sl)->CurrentIRQL = KeGetCurrentIrql(); \
|
|
(_sl)->CurrentThread = PsGetCurrentThread(); \
|
|
}
|
|
|
|
#define NDIS_DPR_UNLOCK(_sl) {\
|
|
(_sl)->LockAcquired = FALSE; \
|
|
strncpy((_sl)->LastReleaseFile, strrchr(__FILE__,'\\')+1, 7); \
|
|
(_sl)->LastReleaseLine = __LINE__; \
|
|
TRACE(LOCKS,(_sl),(_sl)->Lock.OldIrql,"DPR_UNLOCK");\
|
|
NdisDprReleaseSpinLock(&(_sl)->Lock);\
|
|
}
|
|
|
|
#else
|
|
|
|
#define NDIS_INIT_LOCK(_sl) NdisAllocateSpinLock(&(_sl)->Lock)
|
|
#define NDIS_LOCK(_sl) NdisAcquireSpinLock(&(_sl)->Lock)
|
|
#define NDIS_UNLOCK(_sl) NdisReleaseSpinLock(&(_sl)->Lock)
|
|
#define NDIS_DPR_LOCK(_sl) NdisDprAcquireSpinLock(&(_sl)->Lock)
|
|
#define NDIS_DPR_UNLOCK(_sl) NdisDprReleaseSpinLock(&(_sl)->Lock)
|
|
|
|
#endif
|
|
|
|
#if DBG && EXTRA_DBG
|
|
#define VERIFY_LIST(_l) DbgVerifyList(_l)
|
|
#else
|
|
#define VERIFY_LIST(_l)
|
|
#endif
|
|
|
|
#define GpcRemoveEntryList(_pl) {PLIST_ENTRY _q = (_pl)->Flink;VERIFY_LIST(_pl);RemoveEntryList(_pl);InitializeListHead(_pl);VERIFY_LIST(_q);}
|
|
#define GpcInsertTailList(_l,_e) VERIFY_LIST(_l);InsertTailList(_l,_e);VERIFY_LIST(_e)
|
|
#define GpcInsertHeadList(_l,_e) VERIFY_LIST(_l);InsertHeadList(_l,_e);VERIFY_LIST(_e)
|
|
|
|
#if 0
|
|
#define GpcInterlockedInsertTailList(_l,_e,_s) \
|
|
NdisInterlockedInsertTailList(_l,_e,_s)
|
|
|
|
#else
|
|
|
|
#define GpcInterlockedInsertTailList(_l,_e,_s) \
|
|
{NDIS_LOCK(_s);VERIFY_LIST(_l);InsertTailList(_l,_e);VERIFY_LIST(_l);NDIS_UNLOCK(_s);}
|
|
#endif
|
|
|
|
|
|
#if NEW_MRSW
|
|
|
|
#define INIT_LOCK InitializeMRSWLock
|
|
#define READ_LOCK EnterReader
|
|
#define READ_UNLOCK ExitReader
|
|
#define WRITE_LOCK EnterWriter
|
|
#define WRITE_UNLOCK ExitWriter
|
|
|
|
#else
|
|
|
|
#define INIT_LOCK InitializeMRSWLock
|
|
#define READ_LOCK AcquireReadLock
|
|
#define READ_UNLOCK ReleaseReadLock
|
|
#define WRITE_LOCK AcquireWriteLock
|
|
#define WRITE_UNLOCK ReleaseWriteLock
|
|
|
|
#endif
|
|
|
|
//
|
|
// Get the CF index from the client block
|
|
//
|
|
#define GetCFIndexFromClient(_cl) (((PCLIENT_BLOCK)(_cl))->pCfBlock->AssignedIndex)
|
|
|
|
//
|
|
// Get the client index from the client block
|
|
//
|
|
#define GetClientIndexFromClient(_cl) (((PCLIENT_BLOCK)(_cl))->AssignedIndex)
|
|
|
|
//
|
|
// return the blob block pointer for the pattern:
|
|
// for specific patterns - its the blob entry in the CB
|
|
// for generic patterns - its the pBlobBlock
|
|
//
|
|
#define GetBlobFromPattern(_p,_i) (_p)->arpBlobBlock[_i]
|
|
|
|
|
|
//
|
|
// return the index bit to the ULONG
|
|
//
|
|
#define ReleaseClientIndex(_v,_i) _v&=~(1<<_i) // clear the bit
|
|
|
|
//
|
|
// statistics macros
|
|
//
|
|
#define StatInc(_m) (glStat._m)++
|
|
#define StatDec(_m) (glStat._m)--
|
|
#define CfStatInc(_cf,_m) (glStat.CfStat[_cf]._m)++
|
|
#define CfStatDec(_cf,_m) (glStat.CfStat[_cf]._m)--
|
|
#define ProtocolStatInc(_p,_m) (glStat.ProtocolStat[_p]._m)++
|
|
#define ProtocolStatDec(_p,_m) (glStat.ProtocolStat[_p]._m)--
|
|
|
|
/*
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// typedef
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
*/
|
|
|
|
|
|
//
|
|
// completion opcodes
|
|
//
|
|
typedef enum {
|
|
|
|
OP_ANY_CFINFO,
|
|
OP_ADD_CFINFO,
|
|
OP_MODIFY_CFINFO,
|
|
OP_REMOVE_CFINFO
|
|
|
|
} GPC_COMPLETION_OP;
|
|
|
|
|
|
//
|
|
// define object type enum for handle verification
|
|
//
|
|
typedef enum {
|
|
|
|
GPC_ENUM_INVALID,
|
|
GPC_ENUM_CLIENT_TYPE,
|
|
GPC_ENUM_CFINFO_TYPE,
|
|
GPC_ENUM_PATTERN_TYPE
|
|
|
|
} GPC_ENUM_OBJECT_TYPE;
|
|
|
|
|
|
typedef struct _CF_BLOCK CF_BLOCK;
|
|
typedef struct _PATTERN_BLOCK PATTERN_BLOCK;
|
|
|
|
|
|
//
|
|
// A queued notification structure
|
|
//
|
|
typedef struct _QUEUED_NOTIFY {
|
|
|
|
LIST_ENTRY Linkage;
|
|
GPC_NOTIFY_REQUEST_RES NotifyRes;
|
|
PFILE_OBJECT FileObject;
|
|
|
|
} QUEUED_NOTIFY, *PQUEUED_NOTIFY;
|
|
|
|
|
|
//
|
|
// A queued completion structure
|
|
//
|
|
typedef struct _QUEUED_COMPLETION {
|
|
|
|
GPC_COMPLETION_OP OpCode; // what completed
|
|
GPC_HANDLE ClientHandle;
|
|
GPC_HANDLE CfInfoHandle;
|
|
GPC_STATUS Status;
|
|
|
|
} QUEUED_COMPLETION, *PQUEUED_COMPLETION;
|
|
|
|
|
|
//
|
|
// A pending IRP structure
|
|
//
|
|
typedef struct _PENDING_IRP {
|
|
|
|
LIST_ENTRY Linkage;
|
|
|
|
PIRP Irp;
|
|
PFILE_OBJECT FileObject;
|
|
QUEUED_COMPLETION QComp;
|
|
|
|
} PENDING_IRP, *PPENDING_IRP;
|
|
|
|
|
|
#if NEW_MRSW
|
|
|
|
//
|
|
// Multiple Readers Single Write definitions
|
|
// code has been taken from (tdi\tcpipmerge\ip\ipmlock.h)
|
|
//
|
|
|
|
typedef struct _MRSW_LOCK
|
|
{
|
|
KSPIN_LOCK rlReadLock;
|
|
KSPIN_LOCK rlWriteLock;
|
|
LONG lReaderCount;
|
|
} MRSW_LOCK, *PMRSW_LOCK;
|
|
|
|
#else
|
|
|
|
//
|
|
// Multiple Readers Single Write definitions
|
|
// code has been taken from the filter driver project (routing\ip\fltrdrvr)
|
|
//
|
|
|
|
typedef struct _MRSW_LOCK
|
|
{
|
|
KSPIN_LOCK SpinLock;
|
|
LONG ReaderCount;
|
|
} MRSW_LOCK, *PMRSW_LOCK;
|
|
|
|
#endif
|
|
|
|
|
|
//
|
|
// The generic pattern database struct
|
|
//
|
|
typedef struct _GENERIC_PATTERN_DB {
|
|
|
|
MRSW_LOCK Lock;
|
|
Rhizome *pRhizome; // pointer to a Rhizome
|
|
|
|
} GENERIC_PATTERN_DB, *PGENERIC_PATTERN_DB;
|
|
|
|
|
|
|
|
//
|
|
// A client block is used to store specific client context
|
|
//
|
|
typedef struct _CLIENT_BLOCK {
|
|
|
|
//
|
|
// !!! MUST BE FIRST FIELD !!!
|
|
//
|
|
GPC_ENUM_OBJECT_TYPE ObjectType;
|
|
|
|
LIST_ENTRY ClientLinkage; // client blocks list link
|
|
LIST_ENTRY BlobList; // list of blobs of the client
|
|
|
|
CF_BLOCK *pCfBlock;
|
|
GPC_CLIENT_HANDLE ClientCtx;
|
|
ULONG AssignedIndex;
|
|
ULONG Flags;
|
|
ULONG State;
|
|
GPC_LOCK Lock;
|
|
REF_CNT RefCount;
|
|
PFILE_OBJECT pFileObject; // used for async completion
|
|
GPC_HANDLE ClHandle; // handle returned to the client
|
|
GPC_CLIENT_FUNC_LIST FuncList;
|
|
|
|
} CLIENT_BLOCK, *PCLIENT_BLOCK;
|
|
|
|
|
|
//
|
|
// A blob (A.K.A CF_INFO) block holds a GPC header + client specific data
|
|
//
|
|
typedef struct _BLOB_BLOCK {
|
|
|
|
//
|
|
// !!! MUST BE FIRST FIELD !!!
|
|
//
|
|
GPC_ENUM_OBJECT_TYPE ObjectType;
|
|
|
|
LIST_ENTRY ClientLinkage; // linked on the client
|
|
LIST_ENTRY PatternList; // head of pattern linked list
|
|
LIST_ENTRY CfLinkage; // blobs on the CF
|
|
|
|
//PCLIENT_BLOCK pClientBlock; // pointer to installer
|
|
REF_CNT RefCount;
|
|
GPC_STATE State;
|
|
ULONG Flags;
|
|
GPC_CLIENT_HANDLE arClientCtx[MAX_CLIENTS_CTX_PER_BLOB];
|
|
ULONG ClientStatusCountDown;
|
|
GPC_STATUS LastStatus;
|
|
GPC_LOCK Lock;
|
|
CTEBlockStruc WaitBlockAddFailed;
|
|
PCLIENT_BLOCK arpClientStatus[MAX_CLIENTS_CTX_PER_BLOB];
|
|
ULONG ClientDataSize;
|
|
PVOID pClientData;
|
|
ULONG NewClientDataSize;
|
|
PVOID pNewClientData;
|
|
PCLIENT_BLOCK pOwnerClient;
|
|
PCLIENT_BLOCK pCallingClient;
|
|
PCLIENT_BLOCK pCallingClient2;
|
|
HANDLE OwnerClientHandle;
|
|
GPC_CLIENT_HANDLE OwnerClientCtx;
|
|
GPC_HANDLE ClHandle; // handle returned to the client
|
|
// New fields to keep track of the additional information
|
|
//
|
|
// Rules:
|
|
// (1) FileObject is referenced if NOT NULL
|
|
// (2) Pattern needs to be freed if NOT NULL; should be used for AddPattern
|
|
//
|
|
PFILE_OBJECT FileObject;
|
|
PGPC_IP_PATTERN Pattern;
|
|
|
|
//
|
|
|
|
//
|
|
// assume only one client can accept the flow
|
|
//
|
|
PCLIENT_BLOCK pNotifiedClient;
|
|
GPC_CLIENT_HANDLE NotifiedClientCtx;
|
|
|
|
#if NO_USER_PENDING
|
|
CTEBlockStruc WaitBlock;
|
|
#endif
|
|
|
|
} BLOB_BLOCK, *PBLOB_BLOCK;
|
|
|
|
//
|
|
// The classification block is an array of blob pointers
|
|
//
|
|
typedef struct _CLASSIFICATION_BLOCK {
|
|
|
|
REF_CNT RefCount;
|
|
ULONG NumberOfElements;
|
|
HFHandle ClassificationHandle; // how to get back to index tbl
|
|
|
|
// must be last
|
|
PBLOB_BLOCK arpBlobBlock[1];
|
|
|
|
} CLASSIFICATION_BLOCK, *PCLASSIFICATION_BLOCK;
|
|
|
|
//
|
|
// A pattern block holds specific data for the pattern
|
|
//
|
|
typedef struct _PATTERN_BLOCK {
|
|
|
|
//
|
|
// !!! MUST BE FIRST FIELD !!!
|
|
//
|
|
GPC_ENUM_OBJECT_TYPE ObjectType;
|
|
GPC_STATE State;
|
|
|
|
LIST_ENTRY BlobLinkage[GPC_CF_MAX]; // linked on the blob
|
|
LIST_ENTRY TimerLinkage;
|
|
|
|
PBLOB_BLOCK arpBlobBlock[GPC_CF_MAX];
|
|
PCLIENT_BLOCK pClientBlock;
|
|
PCLIENT_BLOCK pAutoClient;
|
|
PCLASSIFICATION_BLOCK pClassificationBlock;
|
|
ULONG WheelIndex;
|
|
REF_CNT RefCount;
|
|
ULONG ClientRefCount;
|
|
ULONG TimeToLive; // for internal patterns
|
|
ULONG Flags;
|
|
ULONG Priority; // for generic pattern
|
|
PVOID DbCtx;
|
|
GPC_LOCK Lock;
|
|
GPC_HANDLE ClHandle; // handle returned to the client
|
|
ULONG ProtocolTemplate;
|
|
|
|
} PATTERN_BLOCK, *PPATTERN_BLOCK;
|
|
|
|
|
|
//
|
|
// A CF block struct. This would construct a linked list of Cf blocks.
|
|
//
|
|
typedef struct _CF_BLOCK {
|
|
|
|
REF_CNT RefCount;
|
|
LIST_ENTRY Linkage; // on the global list
|
|
LIST_ENTRY ClientList; // for the client blocks
|
|
LIST_ENTRY BlobList; // list of blobs
|
|
|
|
ULONG NumberOfClients;
|
|
ULONG AssignedIndex;
|
|
ULONG ClientIndexes;
|
|
GPC_LOCK Lock;
|
|
//MRSW_LOCK ClientSync;
|
|
GPC_LOCK ClientSync;
|
|
ULONG MaxPriorities;
|
|
PGENERIC_PATTERN_DB arpGenericDb[GPC_PROTOCOL_TEMPLATE_MAX];
|
|
|
|
} CF_BLOCK, *PCF_BLOCK;
|
|
|
|
|
|
typedef struct _SPECIFIC_PATTERN_DB {
|
|
|
|
MRSW_LOCK Lock;
|
|
PatHashTable *pDb;
|
|
|
|
} SPECIFIC_PATTERN_DB, *PSPECIFIC_PATTERN_DB;
|
|
|
|
|
|
typedef struct _FRAGMENT_DB {
|
|
|
|
MRSW_LOCK Lock;
|
|
PatHashTable *pDb;
|
|
|
|
} FRAGMENT_DB, *PFRAGMENT_DB;
|
|
|
|
|
|
//
|
|
// A context structure to pass to the pathash scan routine
|
|
//
|
|
typedef struct _SCAN_STRUCT {
|
|
|
|
PCLIENT_BLOCK pClientBlock;
|
|
PPATTERN_BLOCK pPatternBlock;
|
|
PBLOB_BLOCK pBlobBlock;
|
|
ULONG Priority;
|
|
BOOLEAN bRemove;
|
|
|
|
} SCAN_STRUCT, *PSCAN_STRUCT;
|
|
|
|
|
|
//
|
|
// A protocol block holds pointers to databases for a specific
|
|
// protocol template
|
|
//
|
|
typedef struct _PROTOCOL_BLOCK {
|
|
|
|
LIST_ENTRY TimerPatternList[NUMBER_OF_WHEELS];
|
|
ULONG CurrentWheelIndex;
|
|
ULONG SpecificPatternCount;
|
|
ULONG GenericPatternCount;
|
|
ULONG AutoSpecificPatternCount;
|
|
ULONG ProtocolTemplate;
|
|
ULONG PatternSize;
|
|
SPECIFIC_PATTERN_DB SpecificDb;
|
|
PVOID pProtocolDb; // fragments
|
|
GPC_LOCK PatternTimerLock[NUMBER_OF_WHEELS];
|
|
NDIS_TIMER PatternTimer;
|
|
|
|
} PROTOCOL_BLOCK, *PPROTOCOL_BLOCK;
|
|
|
|
|
|
//
|
|
// Global data block
|
|
//
|
|
typedef struct _GLOBAL_BLOCK {
|
|
|
|
LIST_ENTRY CfList; // CF list head
|
|
LIST_ENTRY gRequestList; // Maintain a request list to deal with contention...
|
|
GPC_LOCK Lock;
|
|
GPC_LOCK RequestListLock;
|
|
HandleFactory *pCHTable; // Hash table maps user mode handle to kmode pointer
|
|
MRSW_LOCK ChLock; // lock for pCHTable
|
|
PPROTOCOL_BLOCK pProtocols; // pointer to array of supported protocols
|
|
MM_SYSTEMSIZE SystemSizeHint;
|
|
ULONG AutoPatternLimit;
|
|
|
|
} GLOBAL_BLOCK, *PGLOBAL_BLOCK;
|
|
|
|
|
|
|
|
//
|
|
// TCP Query Context . Allocated before calling TcpQueryInfo.
|
|
// When calling TcpQueryInfo only pass Offset into this structure
|
|
// pointing at RouteInfo.
|
|
// into TCP.
|
|
// Initialize the TcpPattern with remote address and remote port
|
|
// before the call and check on call completion if the values are
|
|
// of relevance : this will happen when protocol = UDP and stack
|
|
// gives us only one IP address on TcpQueryInfo call completion
|
|
//
|
|
typedef struct _GPC_TCP_QUERY_CONTEXT
|
|
{
|
|
PGPC_IP_PATTERN pTcpPattern;
|
|
PMDL pMdl;
|
|
//This should be the last field
|
|
//ROUTING_INFO_ADDR_1_SIZE
|
|
//depends on that
|
|
TDI_ROUTING_INFO RouteInfo;
|
|
} GPC_TCP_QUERY_CONTEXT, *PGPC_TCP_QUERY_CONTEXT;
|
|
|
|
|
|
//
|
|
// New request block. This will be used to store the event and linkage.
|
|
// Therefore, when a thread needs to block, allocate a request_block, allocate
|
|
// an event, grab the requestlist lock , put this on the list and wait.
|
|
//
|
|
typedef struct _REQUEST_BLOCK {
|
|
|
|
LIST_ENTRY Linkage;
|
|
NDIS_EVENT RequestEvent;
|
|
|
|
} REQUEST_BLOCK, *PREQUEST_BLOCK;
|
|
|
|
#if NEW_MRSW
|
|
|
|
//
|
|
// VOID
|
|
// InitRwLock(
|
|
// PMRSW_LOCK pLock
|
|
// )
|
|
//
|
|
// Initializes the spin locks and the reader count
|
|
//
|
|
|
|
#define InitializeMRSWLock(l) { \
|
|
KeInitializeSpinLock(&((l)->rlReadLock)); \
|
|
KeInitializeSpinLock(&((l)->rlWriteLock)); \
|
|
(l)->lReaderCount = 0; \
|
|
}
|
|
|
|
|
|
//
|
|
// VOID
|
|
// EnterReader(
|
|
// PMRSW_LOCK pLock,
|
|
// PKIRQL pCurrIrql
|
|
// )
|
|
//
|
|
// Acquires the Reader Spinlock (now thread is at DPC).
|
|
// InterlockedIncrements the reader count (interlocked because the reader
|
|
// lock is not taken when the count is decremented in ExitReader())
|
|
// If the thread is the first reader, also acquires the Writer Spinlock (at
|
|
// DPC to be more efficient) to block writers
|
|
// Releases the Reader Spinlock from DPC, so that it remains at DPC
|
|
// for the duration of the lock being held
|
|
//
|
|
// If a writer is in the code, the first reader will wait on the Writer
|
|
// Spinlock and all subsequent readers will wait on the Reader Spinlock
|
|
// If a reader is in the code and is executing the EnterReader, then a new
|
|
// reader will wait for sometime on the Reader Spinlock, and then proceed
|
|
// on to the code (at DPC)
|
|
//
|
|
#define EnterReader(l, q) {\
|
|
KeAcquireSpinLock(&((l)->rlReadLock), (q)); \
|
|
TRACE(LOCKS,l,*q,"EnterReader"); \
|
|
if(InterlockedIncrement(&((l)->lReaderCount)) == 1) { \
|
|
TRACE(LOCKS,l,(l)->lReaderCount,"EnterReader1"); \
|
|
KeAcquireSpinLockAtDpcLevel(&((l)->rlWriteLock)); \
|
|
TRACE(LOCKS,l,(l)->rlWriteLock,"EnterReader2"); \
|
|
} \
|
|
TRACE(LOCKS,l,(l)->lReaderCount,"EnterReader3"); \
|
|
KeReleaseSpinLockFromDpcLevel(&((l)->rlReadLock)); \
|
|
}
|
|
|
|
#define EnterReaderAtDpcLevel(l) {\
|
|
KeAcquireSpinLockAtDpcLevel(&((l)->rlReadLock)); \
|
|
if(InterlockedIncrement(&((l)->lReaderCount)) == 1) \
|
|
KeAcquireSpinLockAtDpcLevel(&((l)->rlWriteLock)); \
|
|
KeReleaseSpinLockFromDpcLevel(&((l)->rlReadLock)); \
|
|
}
|
|
|
|
//
|
|
// VOID
|
|
// ExitReader(
|
|
// PMRSW_LOCK pLock,
|
|
// KIRQL kiOldIrql
|
|
// )
|
|
//
|
|
// InterlockedDec the reader count.
|
|
// If this is the last reader, then release the Writer Spinlock to let
|
|
// other writers in
|
|
// Otherwise, just lower the irql to what was before the lock was
|
|
// acquired. Either way, the irql is down to original irql
|
|
//
|
|
|
|
#define ExitReader(l, q) {\
|
|
TRACE(LOCKS,l,q,"ExitReader");\
|
|
if(InterlockedDecrement(&((l)->lReaderCount)) == 0) { \
|
|
TRACE(LOCKS,(l)->rlWriteLock,q,"ExitReader1"); \
|
|
KeReleaseSpinLock(&((l)->rlWriteLock), q); \
|
|
} \
|
|
else { \
|
|
TRACE(LOCKS,l,(l)->lReaderCount,"ExitReader2"); \
|
|
KeLowerIrql(q); \
|
|
} \
|
|
}
|
|
|
|
#define ExitReaderFromDpcLevel(l) {\
|
|
if(InterlockedDecrement(&((l)->lReaderCount)) == 0) \
|
|
KeReleaseSpinLockFromDpcLevel(&((l)->rlWriteLock)); \
|
|
}
|
|
|
|
//
|
|
// EnterWriter(
|
|
// PMRSW_LOCK pLock,
|
|
// PKIRQL pCurrIrql
|
|
// )
|
|
//
|
|
// Acquire the reader and then the writer spin lock
|
|
// If there are readers in the code, the first writer will wait
|
|
// on the Writer Spinlock. All other writers will wait (with readers)
|
|
// on the Reader Spinlock
|
|
// If there is a writer in the code then a new writer will wait on
|
|
// the Reader Spinlock
|
|
|
|
#define EnterWriter(l, q) {\
|
|
KeAcquireSpinLock(&((l)->rlReadLock), (q)); \
|
|
TRACE(LOCKS,l,*q,"EnterWriter"); \
|
|
TRACE(LOCKS,l,(l)->rlWriteLock,"EnterWrite1"); \
|
|
KeAcquireSpinLockAtDpcLevel(&((l)->rlWriteLock)); \
|
|
}
|
|
|
|
#define EnterWriterAtDpcLevel(l) { \
|
|
KeAcquireSpinLockAtDpcLevel(&((l)->rlReadLock)); \
|
|
KeAcquireSpinLockAtDpcLevel(&((l)->rlWriteLock)); \
|
|
}
|
|
|
|
|
|
//
|
|
// ExitWriter(
|
|
// PMRSW_LOCK pLock,
|
|
// KIRQL kiOldIrql
|
|
// )
|
|
//
|
|
// Release both the locks
|
|
//
|
|
|
|
#define ExitWriter(l, q) {\
|
|
TRACE(LOCKS,l,(l)->rlWriteLock,"ExitWrite1"); \
|
|
KeReleaseSpinLockFromDpcLevel(&((l)->rlWriteLock)); \
|
|
TRACE(LOCKS,l,q,"ExitWrite1"); \
|
|
KeReleaseSpinLock(&((l)->rlReadLock), q); \
|
|
}
|
|
|
|
|
|
#define ExitWriterFromDpcLevel(l) {\
|
|
KeReleaseSpinLockFromDpcLevel(&((l)->rlWriteLock)); \
|
|
KeReleaseSpinLockFromDpcLevel(&((l)->rlReadLock)); \
|
|
}
|
|
|
|
#else
|
|
|
|
#define InitializeMRSWLock(_pLock) { \
|
|
(_pLock)->ReaderCount = 0; \
|
|
KeInitializeSpinLock(&((_pLock)->SpinLock)); \
|
|
}
|
|
|
|
#define AcquireReadLock(_pLock,_pOldIrql) { \
|
|
TRACE(LOCKS, _pLock, (_pLock)->ReaderCount, "RL.1"); \
|
|
KeAcquireSpinLock(&((_pLock)->SpinLock),_pOldIrql); \
|
|
InterlockedIncrement(&((_pLock)->ReaderCount)); \
|
|
TRACE(LOCKS, _pLock, (_pLock)->ReaderCount, "RL.2"); \
|
|
KeReleaseSpinLockFromDpcLevel(&((_pLock)->SpinLock)); \
|
|
TRACE(LOCKS, _pLock, *(_pOldIrql), "RL.3"); \
|
|
}
|
|
|
|
#define ReleaseReadLock(_pLock,_OldIrql) { \
|
|
TRACE(LOCKS, _pLock, (_pLock)->ReaderCount, "RU.1"); \
|
|
InterlockedDecrement(&((_pLock)->ReaderCount)); \
|
|
TRACE(LOCKS, _pLock, (_pLock)->ReaderCount, "RU.2"); \
|
|
KeLowerIrql(_OldIrql); \
|
|
TRACE(LOCKS, _pLock, _OldIrql, "RU.3"); \
|
|
}
|
|
|
|
#define AcquireWriteLock(_pLock,_pOldIrql) { \
|
|
TRACE(LOCKS, _pLock, _pOldIrql, "WL.1"); \
|
|
KeAcquireSpinLock(&((_pLock)->SpinLock),_pOldIrql); \
|
|
TRACE(LOCKS, _pLock, (_pLock)->ReaderCount, "WL.2"); \
|
|
while(InterlockedDecrement(&((_pLock)->ReaderCount))>=0)\
|
|
{ \
|
|
InterlockedIncrement (&((_pLock)->ReaderCount)); \
|
|
} \
|
|
TRACE(LOCKS, _pLock, (_pLock)->ReaderCount, "WL.3"); \
|
|
}
|
|
|
|
#define ReleaseWriteLock(_pLock,_OldIrql) { \
|
|
TRACE(LOCKS, _pLock, (_pLock)->ReaderCount, "WU.1"); \
|
|
InterlockedExchange(&(_pLock)->ReaderCount,0); \
|
|
TRACE(LOCKS, _pLock, (_pLock)->ReaderCount, "WU.2"); \
|
|
KeReleaseSpinLock(&((_pLock)->SpinLock),_OldIrql); \
|
|
TRACE(LOCKS, _pLock, _OldIrql, "WU.3"); \
|
|
}
|
|
|
|
#endif
|
|
|
|
#if 1
|
|
|
|
#define RSC_READ_LOCK(_l,_i) NDIS_LOCK(_l)
|
|
#define RSC_READ_UNLOCK(_l,_i) NDIS_UNLOCK(_l)
|
|
#define RSC_WRITE_LOCK(_l,_i) NDIS_LOCK(_l)
|
|
#define RSC_WRITE_UNLOCK(_l,_i) NDIS_UNLOCK(_l)
|
|
|
|
#else
|
|
|
|
#define RSC_READ_LOCK WRITE_LOCK
|
|
#define RSC_READ_UNLOCK WRITE_UNLOCK
|
|
#define RSC_WRITE_LOCK WRITE_LOCK
|
|
#define RSC_WRITE_UNLOCK WRITE_UNLOCK
|
|
|
|
#endif
|
|
|
|
/*
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// IP definitions
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
*/
|
|
|
|
#define DEFAULT_VERLEN 0x45 // Default version and length.
|
|
#define IP_VERSION 0x40
|
|
#define IP_VER_FLAG 0xF0
|
|
#define IP_RSVD_FLAG 0x0080 // Reserved.
|
|
#define IP_DF_FLAG 0x0040 // 'Don't fragment' flag
|
|
#define IP_MF_FLAG 0x0020 // 'More fragments flag'
|
|
#define IP_OFFSET_MASK ~0x00E0 // Mask for extracting offset field.
|
|
|
|
#if (defined(_M_IX86) && (_MSC_FULL_VER > 13009037)) || ((defined(_M_AMD64) || defined(_M_IA64)) && (_MSC_FULL_VER > 13009175))
|
|
#define net_short(_x) _byteswap_ushort((USHORT)(_x))
|
|
#define net_long(_x) _byteswap_ulong(_x)
|
|
#else
|
|
#define net_short(x) ((((x)&0xff) << 8) | (((x)&0xff00) >> 8))
|
|
#define net_long(x) (((((ulong)(x))&0xffL)<<24) | \
|
|
((((ulong)(x))&0xff00L)<<8) | \
|
|
((((ulong)(x))&0xff0000L)>>8) | \
|
|
((((ulong)(x))&0xff000000L)>>24))
|
|
#endif
|
|
/*
|
|
* Protocols (from winsock.h)
|
|
*/
|
|
#define IPPROTO_IP 0 /* dummy for IP */
|
|
#define IPPROTO_ICMP 1 /* control message protocol */
|
|
#define IPPROTO_IGMP 2 /* group management protocol */
|
|
#define IPPROTO_GGP 3 /* gateway^2 (deprecated) */
|
|
#define IPPROTO_TCP 6 /* tcp */
|
|
#define IPPROTO_PUP 12 /* pup */
|
|
#define IPPROTO_UDP 17 /* user datagram protocol */
|
|
#define IPPROTO_IDP 22 /* xns idp */
|
|
#define IPPROTO_ND 77 /* UNOFFICIAL net disk proto */
|
|
#define IPPROTO_IPSEC 51 /* ???????? */
|
|
|
|
#define IPPROTO_RAW 255 /* raw IP packet */
|
|
#define IPPROTO_MAX 256
|
|
|
|
//
|
|
// UDP header definition
|
|
//
|
|
typedef struct _UDP_HEADER {
|
|
ushort uh_src;
|
|
ushort uh_dest;
|
|
ushort uh_length;
|
|
ushort uh_xsum;
|
|
} UDP_HEADER, *PUDP_HEADER;
|
|
|
|
|
|
//
|
|
//* IP Header format.
|
|
//
|
|
typedef struct _IP_HEADER {
|
|
|
|
uchar iph_verlen; // Version and length.
|
|
uchar iph_tos; // Type of service.
|
|
ushort iph_length; // Total length of datagram.
|
|
ushort iph_id; // Identification.
|
|
ushort iph_offset; // Flags and fragment offset.
|
|
uchar iph_ttl; // Time to live.
|
|
uchar iph_protocol; // Protocol.
|
|
ushort iph_xsum; // Header checksum.
|
|
ULONG iph_src; // Source address.
|
|
ULONG iph_dest; // Destination address.
|
|
|
|
} IP_HEADER, *PIP_HEADER;
|
|
|
|
|
|
//
|
|
// Definition of the IPX header.
|
|
//
|
|
typedef struct _IPX_HEADER {
|
|
|
|
USHORT CheckSum;
|
|
UCHAR PacketLength[2];
|
|
UCHAR TransportControl;
|
|
UCHAR PacketType;
|
|
UCHAR DestinationNetwork[4];
|
|
UCHAR DestinationNode[6];
|
|
USHORT DestinationSocket;
|
|
UCHAR SourceNetwork[4];
|
|
UCHAR SourceNode[6];
|
|
USHORT SourceSocket;
|
|
|
|
} IPX_HEADER, *PIPX_HEADER;
|
|
|
|
|
|
/*
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// extern
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
*/
|
|
|
|
extern GLOBAL_BLOCK glData;
|
|
extern GPC_STAT glStat;
|
|
|
|
#ifdef STANDALONE_DRIVER
|
|
extern GPC_EXPORTED_CALLS glGpcExportedCalls;
|
|
#endif
|
|
|
|
// tags
|
|
|
|
extern ULONG ClassificationFamilyTag;
|
|
extern ULONG ClientTag;
|
|
extern ULONG PatternTag;
|
|
extern ULONG CfInfoTag;
|
|
extern ULONG QueuedNotificationTag;
|
|
extern ULONG PendingIrpTag;
|
|
|
|
extern ULONG HandleFactoryTag;
|
|
extern ULONG PathHashTag;
|
|
extern ULONG RhizomeTag;
|
|
extern ULONG GenPatternDbTag;
|
|
extern ULONG FragmentDbTag;
|
|
extern ULONG CfInfoDataTag;
|
|
extern ULONG ClassificationBlockTag;
|
|
extern ULONG ProtocolTag;
|
|
extern ULONG DebugTag;
|
|
extern ULONG TcpPatternTag;
|
|
extern ULONG TcpQueryContextTag;
|
|
|
|
|
|
// Lookaside lists
|
|
|
|
extern NPAGED_LOOKASIDE_LIST ClassificationFamilyLL;
|
|
extern NPAGED_LOOKASIDE_LIST ClientLL;
|
|
extern NPAGED_LOOKASIDE_LIST PatternLL;
|
|
//extern NPAGED_LOOKASIDE_LIST CfInfoLL;
|
|
extern ULONG CfInfoLLSize;
|
|
extern NPAGED_LOOKASIDE_LIST QueuedNotificationLL;
|
|
extern NPAGED_LOOKASIDE_LIST PendingIrpLL;
|
|
|
|
|
|
|
|
/*
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// prototypes
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
*/
|
|
|
|
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
);
|
|
|
|
|
|
GPC_STATUS
|
|
InitSpecificPatternDb(
|
|
IN PSPECIFIC_PATTERN_DB pDb,
|
|
IN ULONG PatternSize
|
|
);
|
|
|
|
GPC_STATUS
|
|
UninitSpecificPatternDb(
|
|
IN PSPECIFIC_PATTERN_DB pDb
|
|
);
|
|
|
|
GPC_STATUS
|
|
InitClassificationHandleTbl(
|
|
IN HandleFactory **ppCHTable
|
|
);
|
|
|
|
VOID
|
|
UninitClassificationHandleTbl(
|
|
IN HandleFactory *pCHTable
|
|
);
|
|
GPC_STATUS
|
|
InitializeGenericDb(
|
|
IN PGENERIC_PATTERN_DB *ppGenericDb,
|
|
IN ULONG NumEntries,
|
|
IN ULONG PatternSize
|
|
);
|
|
|
|
VOID
|
|
UninitializeGenericDb(
|
|
IN PGENERIC_PATTERN_DB *ppGenericDb,
|
|
IN ULONG NumEntries
|
|
);
|
|
|
|
PCLIENT_BLOCK
|
|
CreateNewClientBlock(VOID);
|
|
|
|
VOID
|
|
ReleaseCfBlock(
|
|
IN PCF_BLOCK pCf
|
|
);
|
|
|
|
PCF_BLOCK
|
|
CreateNewCfBlock(
|
|
IN ULONG CfId,
|
|
IN ULONG MaxPriorities
|
|
);
|
|
|
|
VOID
|
|
ReleaseClientBlock(
|
|
IN PCLIENT_BLOCK pClientBlock
|
|
);
|
|
|
|
PPATTERN_BLOCK
|
|
CreateNewPatternBlock(
|
|
IN ULONG Flags
|
|
);
|
|
|
|
VOID
|
|
ReleasePatternBlock(
|
|
IN PPATTERN_BLOCK pPatternBlock
|
|
);
|
|
|
|
PCLASSIFICATION_BLOCK
|
|
CreateNewClassificationBlock(
|
|
IN ULONG NumEntries
|
|
);
|
|
|
|
ULONG
|
|
AssignNewClientIndex(
|
|
IN PCF_BLOCK pCfBlock
|
|
);
|
|
|
|
GPC_STATUS
|
|
AddGenericPattern(
|
|
IN PCLIENT_BLOCK pClient,
|
|
IN PUCHAR pPatternBits,
|
|
IN PUCHAR pMaskBits,
|
|
IN ULONG Priority,
|
|
IN PBLOB_BLOCK pBlob,
|
|
IN PPROTOCOL_BLOCK pProtocol,
|
|
IN OUT PPATTERN_BLOCK *ppPattern
|
|
);
|
|
|
|
|
|
GPC_STATUS
|
|
AddSpecificPattern(
|
|
IN PCLIENT_BLOCK pClient,
|
|
IN PUCHAR pPatternBits,
|
|
IN PUCHAR pMaskBits,
|
|
IN PBLOB_BLOCK pBlob,
|
|
IN PPROTOCOL_BLOCK pProtocol,
|
|
IN OUT PPATTERN_BLOCK *ppPattern,
|
|
OUT PCLASSIFICATION_HANDLE pCH
|
|
);
|
|
|
|
ULONG
|
|
GpcCalcHash(
|
|
IN ULONG ProtocolTempId,
|
|
IN PUCHAR pPattern
|
|
);
|
|
|
|
|
|
VOID
|
|
DereferencePattern(
|
|
IN PPATTERN_BLOCK pPattern
|
|
);
|
|
|
|
VOID
|
|
DereferenceBlob(
|
|
IN PBLOB_BLOCK pBlob
|
|
);
|
|
|
|
PBLOB_BLOCK
|
|
CreateNewBlobBlock(
|
|
IN ULONG ClientDataSize,
|
|
IN PVOID pClientData,
|
|
BOOLEAN fChargeQuota
|
|
);
|
|
|
|
VOID
|
|
ReleaseBlobBlock(
|
|
IN PBLOB_BLOCK pBlobBlock
|
|
);
|
|
|
|
GPC_STATUS
|
|
HandleFragment(
|
|
IN PCLIENT_BLOCK pClientBlock,
|
|
IN PPROTOCOL_BLOCK pProtocol,
|
|
IN BOOLEAN bFirstFrag,
|
|
IN BOOLEAN bLastFrag,
|
|
IN ULONG PacketId,
|
|
IN OUT PPATTERN_BLOCK *ppPatternBlock,
|
|
OUT PBLOB_BLOCK *ppBlob
|
|
);
|
|
|
|
NTSTATUS
|
|
InternalSearchPattern(
|
|
IN PCLIENT_BLOCK pClientBlock,
|
|
IN PPROTOCOL_BLOCK pProtocol,
|
|
IN PVOID pPatternKey,
|
|
OUT PPATTERN_BLOCK *ppPatternBlock,
|
|
OUT PCLASSIFICATION_HANDLE pClassificationHandle,
|
|
IN BOOLEAN bNoCache
|
|
);
|
|
|
|
GPC_STATUS
|
|
InitFragmentDb(
|
|
IN PFRAGMENT_DB *ppFragDb
|
|
);
|
|
|
|
GPC_STATUS
|
|
UninitFragmentDb(
|
|
IN PFRAGMENT_DB pFragDb
|
|
);
|
|
|
|
VOID
|
|
DereferenceClient(
|
|
IN PCLIENT_BLOCK pClient
|
|
);
|
|
|
|
|
|
GPC_STATUS
|
|
ClientAddCfInfo(
|
|
IN PCLIENT_BLOCK pClient,
|
|
IN PBLOB_BLOCK pBlob,
|
|
OUT PGPC_CLIENT_HANDLE pClientCfInfoContext
|
|
);
|
|
|
|
VOID
|
|
ClientAddCfInfoComplete(
|
|
IN PCLIENT_BLOCK pClient,
|
|
IN PBLOB_BLOCK pBlob,
|
|
IN GPC_STATUS Status
|
|
);
|
|
|
|
GPC_STATUS
|
|
ClientModifyCfInfo(
|
|
IN PCLIENT_BLOCK pClient,
|
|
IN PBLOB_BLOCK pBlob,
|
|
IN ULONG CfInfoSize,
|
|
IN PVOID pClientData
|
|
);
|
|
|
|
VOID
|
|
ClientModifyCfInfoComplete(
|
|
IN PCLIENT_BLOCK pClient,
|
|
IN PBLOB_BLOCK pBlob,
|
|
IN GPC_STATUS Status
|
|
);
|
|
|
|
GPC_STATUS
|
|
ClientRemoveCfInfo(
|
|
IN PCLIENT_BLOCK pClient,
|
|
IN PBLOB_BLOCK pBlob,
|
|
IN GPC_CLIENT_HANDLE ClientCfInfoContext
|
|
);
|
|
|
|
VOID
|
|
ClientRemoveCfInfoComplete(
|
|
IN PCLIENT_BLOCK pClient,
|
|
IN PBLOB_BLOCK pBlob,
|
|
IN GPC_STATUS Status
|
|
);
|
|
|
|
GPC_STATUS
|
|
RemoveSpecificPattern(
|
|
IN PCLIENT_BLOCK pClient,
|
|
IN PPROTOCOL_BLOCK pProtocol,
|
|
IN PPATTERN_BLOCK pPattern,
|
|
IN BOOLEAN ForceRemoval,
|
|
IN BOOLEAN DbLocked
|
|
);
|
|
|
|
VOID
|
|
ClientRefsExistForSpecificPattern(
|
|
IN PCLIENT_BLOCK pClient,
|
|
IN PPROTOCOL_BLOCK pProtocol,
|
|
IN PPATTERN_BLOCK pPattern,
|
|
IN BOOLEAN dbLocked
|
|
);
|
|
|
|
VOID
|
|
ReadySpecificPatternForDeletion(
|
|
IN PCLIENT_BLOCK pClient,
|
|
IN PPROTOCOL_BLOCK pProtocol,
|
|
IN PPATTERN_BLOCK pPattern,
|
|
IN BOOLEAN DbLocked
|
|
);
|
|
|
|
GPC_STATUS
|
|
RemoveGenericPattern(
|
|
IN PCLIENT_BLOCK pClient,
|
|
IN PPROTOCOL_BLOCK pProtocol,
|
|
IN PPATTERN_BLOCK pPattern
|
|
);
|
|
|
|
VOID
|
|
ReleaseClassificationBlock(
|
|
IN PCLASSIFICATION_BLOCK pClassificationBlock
|
|
);
|
|
|
|
VOID
|
|
ClearPatternLinks(
|
|
IN PPATTERN_BLOCK pPattern,
|
|
IN PPROTOCOL_BLOCK pProtocol,
|
|
IN ULONG CfIndex
|
|
);
|
|
|
|
VOID
|
|
ModifyCompleteClients(
|
|
IN PCLIENT_BLOCK pClient,
|
|
IN PBLOB_BLOCK pBlob
|
|
);
|
|
|
|
//CLASSIFICATION_HANDLE
|
|
//GetClassificationHandle(
|
|
// IN PCLIENT_BLOCK pClient,
|
|
// IN PPATTERN_BLOCK pPattern
|
|
// );
|
|
|
|
VOID
|
|
FreeClassificationHandle(
|
|
IN PCLIENT_BLOCK pClient,
|
|
IN CLASSIFICATION_HANDLE CH
|
|
);
|
|
|
|
GPC_STATUS
|
|
CleanupBlobs(
|
|
IN PCLIENT_BLOCK pClient
|
|
);
|
|
|
|
|
|
VOID
|
|
GpcReadRegistry();
|
|
|
|
NTSTATUS
|
|
OpenRegKey(
|
|
PHANDLE HandlePtr,
|
|
PWCHAR KeyName
|
|
);
|
|
|
|
NTSTATUS
|
|
GetRegDWORDValue(
|
|
HANDLE KeyHandle,
|
|
PWCHAR ValueName,
|
|
PULONG ValueData
|
|
);
|
|
|
|
VOID
|
|
GPC_REG_READ_DWORD(
|
|
HANDLE hRegKey,
|
|
PWCHAR pwcName,
|
|
PULONG pulData,
|
|
ULONG ulDefault,
|
|
ULONG ulMax,
|
|
ULONG ulMin);
|
|
|
|
|
|
#ifdef STANDALONE_DRIVER
|
|
/*
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// GPC inetrface APIs
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
*/
|
|
|
|
|
|
GPC_STATUS
|
|
GpcGetCfInfoClientContext(
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN CLASSIFICATION_HANDLE ClassificationHandle,
|
|
OUT PGPC_CLIENT_HANDLE pClientCfInfoContext
|
|
);
|
|
|
|
GPC_CLIENT_HANDLE
|
|
GpcGetCfInfoClientContextWithRef(
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN CLASSIFICATION_HANDLE ClassificationHandle,
|
|
IN ULONG Offset
|
|
);
|
|
|
|
GPC_STATUS
|
|
GpcGetUlongFromCfInfo(
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN CLASSIFICATION_HANDLE ClassificationHandle,
|
|
IN ULONG Offset,
|
|
IN PULONG pValue
|
|
);
|
|
|
|
GPC_STATUS
|
|
GpcRegisterClient(
|
|
IN ULONG CfId,
|
|
IN ULONG Flags,
|
|
IN ULONG MaxPriorities,
|
|
IN PGPC_CLIENT_FUNC_LIST pClientFuncList,
|
|
IN GPC_CLIENT_HANDLE ClientContext,
|
|
OUT PGPC_HANDLE pClientHandle
|
|
);
|
|
|
|
GPC_STATUS
|
|
GpcDeregisterClient(
|
|
IN GPC_HANDLE ClientHandle
|
|
);
|
|
|
|
GPC_STATUS
|
|
GpcAddCfInfo(
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN ULONG CfInfoSize,
|
|
IN PVOID pClientCfInfo,
|
|
IN GPC_CLIENT_HANDLE ClientCfInfoContext,
|
|
OUT PGPC_HANDLE pGpcCfInfoHandle
|
|
);
|
|
|
|
|
|
|
|
GPC_STATUS
|
|
GpcAddPattern(
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN ULONG ProtocolTemplate,
|
|
IN PVOID Pattern,
|
|
IN PVOID Mask,
|
|
IN ULONG Priority,
|
|
IN GPC_HANDLE GpcCfInfoHandle,
|
|
OUT PGPC_HANDLE pGpcPatternHandle,
|
|
OUT PCLASSIFICATION_HANDLE pClassificationHandle
|
|
);
|
|
|
|
VOID
|
|
GpcAddCfInfoNotifyComplete(
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN GPC_HANDLE GpcCfInfoHandle,
|
|
IN GPC_STATUS Status,
|
|
IN GPC_CLIENT_HANDLE ClientCfInfoContext
|
|
);
|
|
|
|
GPC_STATUS
|
|
GpcModifyCfInfo (
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN GPC_HANDLE GpcCfInfoHandle,
|
|
IN ULONG CfInfoSize,
|
|
IN PVOID pClientCfInfo
|
|
);
|
|
|
|
VOID
|
|
GpcModifyCfInfoNotifyComplete(
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN GPC_HANDLE GpcCfInfoHandle,
|
|
IN GPC_STATUS Status
|
|
);
|
|
|
|
GPC_STATUS
|
|
GpcRemoveCfInfo (
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN GPC_HANDLE GpcCfInfoHandle
|
|
);
|
|
|
|
VOID
|
|
GpcRemoveCfInfoNotifyComplete(
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN GPC_HANDLE GpcCfInfoHandle,
|
|
IN GPC_STATUS Status
|
|
);
|
|
|
|
GPC_STATUS
|
|
GpcRemovePattern (
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN GPC_HANDLE GpcPatternHandle
|
|
);
|
|
|
|
GPC_STATUS
|
|
GpcClassifyPattern (
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN ULONG ProtocolTemplate,
|
|
IN PVOID pPattern,
|
|
OUT PGPC_CLIENT_HANDLE pClientCfInfoContext,
|
|
IN OUT PCLASSIFICATION_HANDLE pClassificationHandle,
|
|
IN ULONG Offset,
|
|
IN PULONG pValue,
|
|
IN BOOLEAN bNoCache
|
|
);
|
|
|
|
GPC_STATUS
|
|
GpcClassifyPacket (
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN ULONG ProtocolTemplate,
|
|
IN PVOID pNdisPacket,
|
|
IN ULONG TransportHeaderOffset,
|
|
IN PTC_INTERFACE_ID InterfaceId,
|
|
OUT PGPC_CLIENT_HANDLE pClientCfInfoContext,
|
|
OUT PCLASSIFICATION_HANDLE pClassificationHandle
|
|
);
|
|
|
|
GPC_STATUS
|
|
GpcEnumCfInfo (
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN OUT PHANDLE pCfInfoHandle,
|
|
OUT PHANDLE pCfInfoMapHandle,
|
|
IN OUT PULONG pCfInfoCount,
|
|
IN OUT PULONG pBufferSize,
|
|
OUT PGPC_ENUM_CFINFO_BUFFER Buffer
|
|
);
|
|
|
|
#endif // STANDALONE_DRIVER
|
|
|
|
GPC_STATUS
|
|
GetClientCtxAndUlongFromCfInfo(
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN OUT PCLASSIFICATION_HANDLE pClassificationHandle,
|
|
OUT PGPC_CLIENT_HANDLE pClientCfInfoContext,
|
|
IN ULONG Offset,
|
|
IN PULONG pValue
|
|
);
|
|
|
|
|
|
GPC_STATUS
|
|
privateGpcAddCfInfo(
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN ULONG CfInfoSize,
|
|
IN PVOID pClientCfInfoPtr,
|
|
IN GPC_CLIENT_HANDLE ClientCfInfoContext,
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PGPC_IP_PATTERN Pattern,
|
|
OUT PGPC_HANDLE pGpcCfInfoHandle
|
|
);
|
|
|
|
GPC_STATUS
|
|
privateGpcRemoveCfInfo(
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN GPC_HANDLE GpcCfInfoHandle,
|
|
IN ULONG Flags
|
|
);
|
|
|
|
GPC_STATUS
|
|
privateGpcRemovePattern(
|
|
IN GPC_HANDLE ClientHandle,
|
|
IN GPC_HANDLE GpcPatternHandle,
|
|
IN BOOLEAN ForceRemoval,
|
|
IN BOOLEAN DbLocked
|
|
);
|
|
|
|
VOID
|
|
UMClientRemoveCfInfoNotify(
|
|
IN PCLIENT_BLOCK pClient,
|
|
IN PBLOB_BLOCK pBlob
|
|
);
|
|
|
|
|
|
VOID
|
|
UMCfInfoComplete(
|
|
IN GPC_COMPLETION_OP OpCode,
|
|
IN PCLIENT_BLOCK pClient,
|
|
IN PBLOB_BLOCK pBlob,
|
|
IN GPC_STATUS Status
|
|
);
|
|
|
|
VOID
|
|
CloseAllObjects(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
IoctlInitialize(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PULONG InitShutdownMask
|
|
);
|
|
|
|
NTSTATUS
|
|
CheckQueuedNotification(
|
|
IN PIRP Irp,
|
|
IN OUT ULONG *outputBufferLength
|
|
);
|
|
|
|
NTSTATUS
|
|
CheckQueuedCompletion(
|
|
IN PQUEUED_COMPLETION pQItem,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
VOID
|
|
PatternTimerExpired(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID FunctionContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3
|
|
);
|
|
|
|
GPC_STATUS
|
|
AddSpecificPatternWithTimer(
|
|
IN PCLIENT_BLOCK pClient,
|
|
IN ULONG ProtocolTemplate,
|
|
IN PVOID PatternKey,
|
|
OUT PPATTERN_BLOCK *ppPattern,
|
|
OUT PCLASSIFICATION_HANDLE pClassificationHandle
|
|
);
|
|
|
|
NTSTATUS
|
|
InitPatternTimer(
|
|
IN ULONG ProtocolTemplate
|
|
);
|
|
|
|
|
|
#endif // __GPCDEF
|