I write the protocol driver, NDIS 5.0. I test it on Win 7 x86. At unloding of the driver after call NdisDeregisterProtocol there is cyclical call UnbindAdapterHandler.
The source code of handlers:
VOID NdisBindAdapter(
PNDIS_STATUS Status,
NDIS_HANDLE BindContext,
PNDIS_STRING DeviceName,
PVOID SystemSpecific1,
PVOID SystemSpecific2
)
{
NDIS_STATUS nsts = STATUS_SUCCESS, OpenErrorStatus = NDIS_STATUS_SUCCESS;
NDIS_MEDIUM Medium = {NdisMedium802_3};
UINT MediumIdx = 0;
PADAPTERDATA adpdata;
DbgPrint(“NdisBindAdapter –>\n”);
if (devext.AdapterCnt>=1)
{
*Status = NDIS_STATUS_OPEN_FAILED;
return;
}
adpdata = ExAllocatePoolWithTag(NonPagedPool, sizeof(ADAPTERDATA), ‘ADRA’);
if (adpdata == NULL)
{
*Status = NDIS_STATUS_OPEN_FAILED;
return;
}
RtlZeroMemory(adpdata, sizeof(ADAPTERDATA));
adpdata->AdapterName.Length = 0;
adpdata->AdapterName.MaximumLength = (USHORT)(DeviceName->Length + sizeof(UNICODE_NULL));
adpdata->AdapterName.Buffer = ExAllocatePoolWithTag(PagedPool, adpdata->AdapterName.MaximumLength, ‘ENRA’);
if (adpdata->AdapterName.Buffer == NULL)
{
*Status = NDIS_STATUS_OPEN_FAILED;
return;
}
RtlZeroMemory(adpdata->AdapterName.Buffer, adpdata->AdapterName.MaximumLength);
RtlCopyUnicodeString(&adpdata->AdapterName, DeviceName);
NdisInitializeEvent(&adpdata->EvtOpenWait);
NdisInitializeEvent(&adpdata->EvtReqWait);
NdisInitializeEvent(&adpdata->EvtCloseWait);
NdisResetEvent(&adpdata->EvtOpenWait);
NdisOpenAdapter(Status, &OpenErrorStatus, &(adpdata->hAdapter), &MediumIdx, &Medium[0], 1, devext.hProto,
(NDIS_HANDLE)adpdata, &(adpdata->AdapterName), 0, NULL);
DbgPrint(“Status = 0x%08X, OpenErrorStatus = 0x%08X\n”, *Status, OpenErrorStatus);
if (NT_SUCCESS(*Status))
{
if (*Status == NDIS_STATUS_SUCCESS)
{
DbgPrint(“MediumIdx = %u\n”, MediumIdx);
NdisOpenAdapterComplete(adpdata, NDIS_STATUS_SUCCESS, NDIS_STATUS_SUCCESS);
}
else
if (*Status == NDIS_STATUS_PENDING)
{
*Status = NDIS_STATUS_SUCCESS;
DbgPrint(“NdisOpenAdapter pending…\n”);
NdisWaitEvent(&adpdata->EvtOpenWait, 0);
}
}
else
{
DbgPrint(“NdisOpenAdapter FAILED! Status = 0x%08X\n”, *Status);
*Status = STATUS_UNSUCCESSFUL;
return;
}
devext.AdapterCnt++;
DbgPrint(“NdisBindAdapter <–\n”);
}
VOID NdisUnbindAdapter(PNDIS_STATUS Status, NDIS_HANDLE ProtocolBindingContext, NDIS_HANDLE UnbindContext)
{
PADAPTERDATA adpdata;
DbgPrint(“–> NdisUnbindAdapter\n”);
adpdata = (PADAPTERDATA)ProtocolBindingContext;
if (adpdata->hAdapter != INVALID_HANDLE_VALUE)
{
NdisResetEvent(&adpdata->EvtCloseWait);
NdisCloseAdapter(Status, &adpdata->hAdapter);
if (NT_SUCCESS(*Status))
{
if (*Status == NDIS_STATUS_PENDING)
{
DbgPrint(“NdisCloseAdapter pending…\n”);
NdisWaitEvent(&adpdata->EvtCloseWait, 0);
*Status = NDIS_STATUS_SUCCESS;
}
adpdata->hAdapter = INVALID_HANDLE_VALUE;
}
else
{
*Status = STATUS_UNSUCCESSFUL;
DbgPrint(“NdisCloseAdapter FAILED!\n”);
}
}
DbgPrint(“<– NdisUnbindAdapter\n”);
}