//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
Module Name:
protocol.c
Abstract:
The Ndis Intermediate Miniport driver sample. This is a passthru driver
which doesn't touch packets at all. The protocol API is implemented
in the following code.
Author:
The original code was a NT/XP sample passthru driver.
KarelD - add CE specific code and reformat text.
Environment:
Windows CE
Revision History:
None.
--*/
#include "precomp.h"
#pragma hdrstop
//------------------------------------------------------------------------------
#define MAX_PACKET_POOL_SIZE 4096
#define MIN_PACKET_POOL_SIZE 64
//------------------------------------------------------------------------------
VOID
ProtocolBindAdapter(
OUT PNDIS_STATUS pStatus,
IN NDIS_HANDLE hBindContext,
IN PNDIS_STRING psAdapterName,
IN PVOID pvSystemSpecific1,
IN PVOID pvSystemSpecific2
)
/*++
Routine Description:
Called by NDIS to bind to a miniport below.
Arguments:
pStatus - Return status of bind here.
hBindContext - Can be passed to NdisCompleteBindAdapter if this call is
pended.
psAdapterName - Device name to bind to. This is passed to NdisOpenAdapter.
pvSystemSpecific1 - Can be passed to NdisOpenProtocolConfiguration to read
per-binding information
pvSystemSpecific2 - Unused
Return Value:
NDIS_STATUS_PENDING - If this call is pended. In this case call
NdisCompleteBindAdapter to complete.
NDIS_xxxx - Completes this call synchronously 同步地
--*/
{
NDIS_STATUS status;
NDIS_STATUS statusOpen;
NDIS_HANDLE hConfig = NULL;
NDIS_STRING sUnbind = NDIS_STRING_CONST("Unbind");
//NDIS_STRING is a counted, zero-terminated Unicode string.
//This data type is used for all NDIS string operations.
//typedef UNICODE_STRING NDIS_STRING, *PNDIS_STRING
//typedef unsigned int UINT;
PNDIS_CONFIGURATION_PARAMETER pValue = NULL;
BINDING* pBinding = NULL;
UINT uiMediumIndex;
ULONG ulSize;
#ifdef UNDER_CE
BOOLEAN bProtocolUnbind = FALSE;
LPWSTR mszProtocols = NULL;
TCHAR mszOldProtocols[256] = _T("");
DWORD dwOldProtocolsSize = 0;
WCHAR wszSkipTheseNICs[][16] = { {L"L2TP"},{L"PPTP"},{L"ASYNCMAC"},{L"IRSIR"},{L"PPPOE"},{L'\0'} };
INT i=0;
#endif
DBGPRINT(("==>PASSTHRU::ProtocolBindAdapter %S\n", psAdapterName->Buffer));
#ifdef UNDER_CE
// We have to avoid recursive 递归binding
//NdisEqualMemory compares the initial Length bytes in the first block of memory to the initial Length bytes
//in the second block of memory. The data type of anything in the compared memory blocks is irrelevant.
//The default return value is 0. If the compared blocks are the same, the return value is 1.
if (NdisEqualMemory(
psAdapterName->Buffer, PASSTHRU_MINIPORT_PREFIX,
PASSTHRU_MINIPORT_PREFIX_SIZE * sizeof(WCHAR)
)) {
status = NDIS_STATUS_NOT_ACCEPTED;
goto cleanUp;
}
//
// This is to skip certain adapters to which passthru can not bind, which is required mostly when
// passthru is loaded dynamically using "s ndisconfig miniport add passthru". At boot time
// passthru is invoked to bind before any protocol driver & hence following is not required for
// that case. Note that adapters like IRSIR1 don't like even getting unbound from IRSIR &
// hence best way is to avoid binding to such adapters.
//
while (wszSkipTheseNICs[i][0] != L'\0')
{
NDIS_STRING sSkipThis;
NdisInitUnicodeString(&sSkipThis,wszSkipTheseNICs[i]);
//Using NdisEqualMemory instead of NdisEqualString to avoid instance number 比较前缀
//Eg. IRSIR1 compared with IRSIR
/*IrSIR is an NDIS miniport driver that binds to the IRDA stack and is only exposed through Winsock.
The IrCOMM driver, which talks to IrSIR through Winsock, creates the virtual COM port.
The IrSIR driver creates an additional COM port.*/
//psAdapterName->Buffer : Points to the first block of memory to be compared
if (NdisEqualMemory(
psAdapterName->Buffer, sSkipThis.Buffer,sSkipThis.Length)) {
status = NDIS_STATUS_NOT_ACCEPTED;
goto cleanUp;
}
++i;
}
//具体操作psAdapterName->Buffer和各种NIC调用NdisEqualMemory进行判断
//上面为解除对passthru不支持的适配器的绑定.
#endif
//
// Access the configuration section for our binding-specific
// parameters. If there is no protocol configuration use default settings.
// pvSystemSpecific1: Pointer to a counted string specified in the system-default character set,
//naming the NDIS driver, effectively the adapter, for which the Parms\ProtocolName key in the
//registry protocol section should be opened.
NdisOpenProtocolConfiguration(&status, &hConfig, pvSystemSpecific1);
if (status == NDIS_STATUS_SUCCESS) {
//
// Read the "Unbind" reserved key that can control which protocols will
// be unbinded解开 from the adapter after it's open
//NdisParameterMultiString: Specifies a multistring parameter of the defined REG_MULTI_SZ type.
NdisReadConfiguration(
&status, &pValue, hConfig, &sUnbind, NdisParameterMultiString
);
if (status != NDIS_STATUS_SUCCESS) pValue = NULL;
}
//
// Allocate memory for the Adapter structure. This represents both the
// protocol context as well as the adapter structure when the miniport
// is initialized.
//
// In addition to the base structure, allocate space for the device
// instance string.
//分配内存给绑定、PASSTHRU_MINIPORT_PREFIX和AdapterName。
ulSize = sizeof(BINDING);//bingding 结构在头文件中定义。
ulSize += PASSTHRU_MINIPORT_PREFIX_SIZE * sizeof(WCHAR);
ulSize += psAdapterName->MaximumLength;
NdisAllocateMemoryWithTag(&pBinding, ulSize, PASSTHRU_MEMORY_TAG);
// ulSize大于Binding结构的大小.*(&pBinding) =pBinding=virtual address of Binding struct.
//&pBinding 是指向Binding结构虚拟地址的指针.
if (pBinding == NULL) {
status = NDIS_STATUS_RESOURCES;
goto cleanUp;
}
NdisInterlockedIncrement(&pBinding->nRef);// Number of references to structure
// NdisInterlockedIncrement can safely be used on variables in pageable memory.
// NdisInterlockedIncrement is atomic only with respect to other NdisInterlockedXXX calls.
// Initialize the adapter structure. We should create there adapter name
// for IM instance. We should save it as well, because we may need to use it
// in a call to NdisIMCancelInitializeDeviceInstance. We only prepare name
// and finish it after we succesfully open the underlying adapter.
//pbinding的值其实是内存中存放驱动binding结构的某个地址。
//即pbinding是指向binding结构的指针。
NdisZeroMemory(pBinding, ulSize);// VOID NdisZeroMemory(PVOID Destination,ULONG Length);
NdisMoveMemory(
(UCHAR*)pBinding + sizeof(BINDING), PASSTHRU_MINIPORT_PREFIX,
PASSTHRU_MINIPORT_PREFIX_SIZE * sizeof(WCHAR)
);//把分配内存中的后面一部分放入PASSTHRU_MINIPORT的prefix.
NdisMoveMemory(
(UCHAR*)pBinding + sizeof(BINDING) +
PASSTHRU_MINIPORT_PREFIX_SIZE * sizeof(WCHAR),
psAdapterName->Buffer, psAdapterName->MaximumLength
);//把最后部分存放适配器的名字 。
pBinding->sDeviceName.MaximumLength = psAdapterName->MaximumLength
+ PASSTHRU_MINIPORT_PREFIX_SIZE * sizeof(WCHAR);
pBinding->sDeviceName.Length = psAdapterName->Length
+ PASSTHRU_MINIPORT_PREFIX_SIZE * sizeo
- 1
- 2
前往页