EXPORT
NdisInitializeWrapper(
OUT PNDIS_HANDLE NdisWrapperHandle,
IN PVOID SystemSpecific1,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
/*
* FUNCTION: Notifies the NDIS library that a new miniport is initializing
* ARGUMENTS:
* NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
* SystemSpecific1 = Pointer to the driver's driver object
* SystemSpecific2 = Pointer to the driver's registry path
* SystemSpecific3 = Always NULL
* NOTES:
* - SystemSpecific2 goes invalid so we copy it
*/
{
PNDIS_M_DRIVER_BLOCK Miniport;
PUNICODE_STRING RegistryPath;
WCHAR *RegistryBuffer;
//
// We will disable the check for hang timeout so we do not
// need a check for hang handler!
//
MChars.CheckForHangHandler = NULL;
MChars.ReturnPacketHandler = MPReturnPacket;
//
// Either the Send or the SendPackets handler should be specified.
// If SendPackets handler is specified, SendHandler is ignored
//
MChars.SendHandler = NULL; // MPSend;
MChars.SendPacketsHandler = MPSendPackets;
Status = NdisIMRegisterLayeredMiniport(NdisWrapperHandle,
&MChars,
sizeof(MChars),
&DriverHandle);
我们来看看NdisMRegisterMiniport做了什么
NDIS_STATUS
EXPORT
NdisMRegisterMiniport(
IN NDIS_HANDLE NdisWrapperHandle,
IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
IN UINT CharacteristicsLength)
/*
* FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
* ARGUMENTS:
* NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
* MiniportCharacteristics = Pointer to a buffer with miniport characteristics
* CharacteristicsLength = Number of bytes in characteristics buffer
* RETURNS:
* Status of operation
*/
{
UINT MinSize;
PNDIS_M_DRIVER_BLOCK Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
PNDIS_M_DRIVER_BLOCK *MiniportPtr;
NTSTATUS Status;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
switch (MiniportCharacteristics->MajorNdisVersion)
{
case 0x03:
MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS);
break;
case 0x04:
MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS);
break;
case 0x05:
MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS);
break;
/*
* Get name of the Linkage registry key for our adapter. It's located under
* the driver key for our driver and so we have basicly two ways to do it.
* Either we can use IoOpenDriverRegistryKey or compose it using information
* gathered by IoGetDeviceProperty. I choosed the second because
* IoOpenDriverRegistryKey wasn't implemented at the time of writing.
*/
Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
0, NULL, &DriverKeyLength);
if (Status != STATUS_BUFFER_TOO_SMALL)
{
NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport driver key length.\n"));
return Status;
}
// Now register the protocol.
//
NdisZeroMemory(&PChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
PChars.MajorNdisVersion = PASSTHRU_PROT_MAJOR_NDIS_VERSION;
PChars.MinorNdisVersion = PASSTHRU_PROT_MINOR_NDIS_VERSION;
//
// Make sure the protocol-name matches the service-name
// (from the INF) under which this protocol is installed.
// This is needed to ensure that NDIS can correctly determine
// the binding and call us to bind to miniports below.
//
NdisInitUnicodeString(&Name, L"Passthru"); // Protocol name
PChars.Name = Name;
PChars.OpenAdapterCompleteHandler = PtOpenAdapterComplete;
PChars.CloseAdapterCompleteHandler = PtCloseAdapterComplete;
PChars.SendCompleteHandler = PtSendComplete;
PChars.TransferDataCompleteHandler = PtTransferDataComplete;
VOID
EXPORT
NdisRegisterProtocol(
OUT PNDIS_STATUS Status,
OUT PNDIS_HANDLE NdisProtocolHandle,
IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics,
IN UINT CharacteristicsLength)
/*
* FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
* ARGUMENTS:
* Status = Address of buffer for status information
* NdisProtocolHandle = Address of buffer for handle used to identify the driver
* ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
* CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
* NOTES:
* - you *must* set NdisProtocolHandle before doing anything that could wind up
* getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
* - the above implies that the initialization of the protocol block must be complete
* by then
* TODO:
* - break this function up - probably do a 'ndisRefreshProtocolBindings' function
* - make this thing able to handle >1 protocol
*/
{
PPROTOCOL_BINDING Protocol;
NTSTATUS NtStatus;
UINT MinSize;
HANDLE DriverKeyHandle = NULL;
PKEY_VALUE_PARTIAL_INFORMATION KeyInformation = NULL;
WCHAR *DataPtr;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
/* first validate the PROTOCOL_CHARACTERISTICS */
switch (ProtocolCharacteristics->MajorNdisVersion)
{
case 0x03:
/* we don't really want to support ndis3 drivers - so we complain for now */
NDIS_DbgPrint(MID_TRACE, ("NDIS 3 protocol attempting to register\n"));
MinSize = sizeof(NDIS30_PROTOCOL_CHARACTERISTICS);
break;
case 0x04:
MinSize = sizeof(NDIS40_PROTOCOL_CHARACTERISTICS);
break;
case 0x05:
MinSize = sizeof(NDIS50_PROTOCOL_CHARACTERISTICS);
break;
/*
* bind the protocol to all of its miniports
*
* open registry path
* get list of devices from Bind key
* call BindAdapterHandler for each
*/
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING RegistryPath;
WCHAR *RegistryPathStr;
RtlInitUnicodeString(&DeviceName, DataPtr); /* we know this is 0-term */
/*
* RegistryPath should be:
* \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
*
* This is constructed as follows:
* SERVICES_KEY + extracted device name + Protocol name from characteristics
*/
if(*Status == NDIS_STATUS_SUCCESS)
{
/* Put protocol binding struct on global list */
ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
}
/*
else if(*Status != NDIS_STATUS_PENDING)
{
// what to do here?
}
*/
}
*Status = NDIS_STATUS_SUCCESS;
}
它首先判断NDIS_PROTOCOL_CHARACTERISTICS的有效性,然后初始化了一个PPROTOCOL_BINDING Protocol结构,然后从Bind key获得设备链表,获得设备名,并创建了这样 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
*的注册表键,然后调用我们传进去的BindAdapterHandler进行绑定设备。并把Protocol加如链表。从*NdisProtocolHandle = Protocol我们知道NdisProtocolHandle 指向Protocol那让我们看看这个Protocol是什么,
typedef struct _PROTOCOL_BINDING {
LIST_ENTRY ListEntry; /* Entry on global list */
KSPIN_LOCK Lock; /* Protecting spin lock */
NDIS_PROTOCOL_CHARACTERISTICS Chars; /* Characteristics */
WORK_QUEUE_ITEM WorkItem; /* Work item */
LIST_ENTRY AdapterListHead; /* List of adapter bindings */
} PROTOCOL_BINDING, *PPROTOCOL_BINDING;
这里面有个指向adapter bindings的链表,来让我们看看adapter binding
LIST_ENTRY ListEntry; /* Entry on global list */
LIST_ENTRY ProtocolListEntry; /* Entry on protocol binding adapter list */
LIST_ENTRY AdapterListEntry; /* Entry on logical adapter list */
KSPIN_LOCK Lock; /* Protecting spin lock */
PPROTOCOL_BINDING ProtocolBinding; /* Protocol that opened adapter */
PLOGICAL_ADAPTER Adapter; /* Adapter opened by protocol */
} ADAPTER_BINDING, *PADAPTER_BINDING;
我们看到第一项是一个NdisOpenBlock结构,现在很多的NDIS放火墙就是通过注册协议根据返回的NdisProtocolHandle来找到NdisOpenBlock结构的,因为NdisOpenBlock结构是用来描述和该ndis protocol有联系的所有ndis miniport和该ndisprotocol绑定的状态每个绑定的send(packets)handler和receive(packet)handler都在这个ndis open block里面。
//
// The stuff below is for CO drivers/protocols. This part is not allocated for CL drivers.
//
struct _NDIS_OPEN_CO
{
....
};
#endif
};
typedef struct _NDIS_COMMON_OPEN_BLOCK
{
PVOID MacHandle; // needed for backward compatibility
NDIS_HANDLE BindingHandle; // Miniport's open context
PNDIS_MINIPORT_BLOCK MiniportHandle; // pointer to the miniport
PNDIS_PROTOCOL_BLOCK ProtocolHandle; // pointer to our protocol
NDIS_HANDLE ProtocolBindingContext;// context when calling ProtXX funcs
PNDIS_OPEN_BLOCK MiniportNextOpen; // used by adapter's OpenQueue
PNDIS_OPEN_BLOCK ProtocolNextOpen; // used by protocol's OpenQueue
NDIS_HANDLE MiniportAdapterContext; // context for miniport
BOOLEAN Reserved1;
BOOLEAN Reserved2;
BOOLEAN Reserved3;
BOOLEAN Reserved4;
PNDIS_STRING BindDeviceName;
KSPIN_LOCK Reserved5;
PNDIS_STRING RootDeviceName;
//
// These are referenced by the macros used by protocols to call.
// All of the ones referenced by the macros are internal NDIS handlers for the miniports
//
union
{
SEND_HANDLER SendHandler;
WAN_SEND_HANDLER WanSendHandler;
};
TRANSFER_DATA_HANDLER TransferDataHandler;
//
// These are referenced internally by NDIS
//
SEND_COMPLETE_HANDLER SendCompleteHandler;
TRANSFER_DATA_COMPLETE_HANDLER TransferDataCompleteHandler;
RECEIVE_HANDLER ReceiveHandler;
RECEIVE_COMPLETE_HANDLER ReceiveCompleteHandler;
WAN_RECEIVE_HANDLER WanReceiveHandler;
REQUEST_COMPLETE_HANDLER RequestCompleteHandler;