📄 openclos.c
字号:
// openclos.c - PacketBindAdapter, PacketBindAdapterComplete,
// PacketUnbindAdapter, PacketUnbindAdapterComplete,
// PacketCleanUp, PacketReset, PacketResetComplete
// Original code by William Ingle (address unknown)
// debugged and extended by Chris Chlap (chrisc@fir.canberra.edu.au)
#include <basedef.h>
#include <vmm.h>
#include <ndis.h>
#include <vwin32.h>
#include <debug.h>
#include "packet.h"
#pragma VxD_LOCKED_CODE_SEG
#pragma VxD_LOCKED_DATA_SEG
//--------------------------------------------------------------------
//
// PacketBindAdapter - bind this driver to a NIC
//
//--------------------------------------------------------------------
VOID NDIS_API PacketBindAdapter(OUT PNDIS_STATUS pStatus,
IN NDIS_HANDLE BindAdapterContext,
IN PNDIS_STRING pAdapterName,
IN PVOID SystemSpecific1,
IN PVOID SystemSpecific2)
{
PDEVICE_EXTENSION pde;
POPEN_INSTANCE oiNew;
NDIS_STATUS ErrorStatus, AllocStatus;
UINT Medium;
NDIS_MEDIUM MediumArray=NdisMedium802_3;
// NDIS_MEDIUM MediumArray=NdisMediumWan;
UINT i;
PWRAPPER_PROTOCOL_BLOCK pWPBlock;
PNDIS_PROTOCOL_CHARACTERISTICS pNPChar;
pde = GlobalDeviceExtension;
//
// allocate some memory for the open structure
//
NdisAllocateMemory((PVOID *)&oiNew, sizeof( OPEN_INSTANCE ), 0, -1);
if (oiNew == NULL) {
// not enough memory
*pStatus = NDIS_STATUS_RESOURCES;
Debug_Out("PacketBindAdapter: ERROR: no memory for Open\n");
return;
}
NdisZeroMemory((PVOID)oiNew, sizeof(OPEN_INSTANCE));
// Save Binding Context
oiNew->BindAdapterContext = BindAdapterContext;
// Save the device handle
oiNew->hDevice = (DWORD) SystemSpecific1;
//
// Allocate a packet pool for our xmit and receive packets
//
NdisAllocatePacketPool(&AllocStatus,
&(oiNew->PacketPool),
TRANSMIT_PACKETS,
sizeof(PACKET_RESERVED));
if (AllocStatus != NDIS_STATUS_SUCCESS) {
// not enough memory
NdisFreeMemory( oiNew, sizeof(OPEN_INSTANCE), 0);
*pStatus = NDIS_STATUS_RESOURCES;
Debug_Out("PacketBindAdapter: ERROR: no memory for Packet Pool\n");
return;
}
//
// Allocate a buffer pool for our xmit and receive buffers
//
NdisAllocateBufferPool(&AllocStatus, &(oiNew->BufferPool), TRANSMIT_PACKETS);
if (AllocStatus != NDIS_STATUS_SUCCESS) {
// not enough memory
//BUG: free packet pool first
NdisFreeMemory(oiNew, sizeof(OPEN_INSTANCE), 0);
*pStatus = NDIS_STATUS_RESOURCES;
Debug_Out("PacketBindAdapter: ERROR: no memory for Buffer Pool\n");
return;
}
//
// list to hold irp's that want to reset the adapter
//
NdisAllocateSpinLock(&(oiNew->ResetSpinLock));
InitializeListHead(&(oiNew->ResetIrpList));
//
// Initialize list for holding pending read requests
//
NdisAllocateSpinLock(&(oiNew->RcvQSpinLock));
InitializeListHead(&(oiNew->RcvList));
//
// Initialize the request list
//
NdisAllocateSpinLock(&(oiNew->RequestSpinLock));
InitializeListHead(&(oiNew->RequestList));
//
// link up the request stored in our open block
//
for (i=0; i<MAX_REQUESTS; i++) {
InsertTailList(&(oiNew->RequestList),
&(oiNew->Requests[i].Reserved.ListElement));
}
//
// Try to open the MAC
//
NdisOpenAdapter(pStatus, &ErrorStatus, &oiNew->AdapterHandle, &Medium,
&MediumArray, 1, pde->NdisProtocolHandle, oiNew,
pAdapterName, 0, NULL);
//
// Test for protocol name and adapter name
//
pWPBlock = ((PWRAPPER_OPEN_BLOCK)(oiNew->AdapterHandle))->ProtocolHandle;
pNPChar = &pWPBlock->ProtocolCharacteristics;
//
// Save the status returned by NdisOpenAdapter for completion routine
//
oiNew->Status = *pStatus;
switch (*pStatus) {
case NDIS_STATUS_PENDING:
Debug_Out("PacketBindAdapter: NdisOpenAdapter: Status Pending\n");
break;
case NDIS_STATUS_SUCCESS:
ErrorStatus = NDIS_STATUS_SUCCESS;
// fall through to completion routine with oiNew->Status
// set to !NDIS_STATUS_PENDING
default:
PacketBindAdapterComplete(oiNew, *pStatus, ErrorStatus);
break;
}
return;
}
//--------------------------------------------------------------------
//
// PacketBindAdapterComplete - upcall on Bind completion
//
//--------------------------------------------------------------------
VOID NDIS_API PacketBindAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN NDIS_STATUS OpenErrorStatus)
{
POPEN_INSTANCE Open;
Open = (POPEN_INSTANCE)ProtocolBindingContext;
//
// If the binding is unsuccessful then we deallocate data structures in
// preparation for unloading
//
if (Status != NDIS_STATUS_SUCCESS) {
NdisFreeSpinLock(&Open->RequestSpinLock);
NdisFreeSpinLock(&Open->RcvQSpinLock);
NdisFreeBufferPool(Open->BufferPool);
NdisFreePacketPool(Open->PacketPool);
NdisFreeMemory(Open, sizeof(OPEN_INSTANCE), 0);
Debug_Out("PacketBindAdapterComplete: ERROR: could not bind\n");
return;
}
//
// Insert New Adapter into list
//
InsertTailList(&GlobalDeviceExtension->OpenList, &Open->ListElement);
//
// If the Open->Status == NDIS_STATUS_PENDING
// then we must complete the pended binding
//
// Apparently, it is safe to NOT call NdisCompleteBindAdapter, even if
// Open->Status == NDIS_STATUS_PENDING
// if (Open->Status == NDIS_STATUS_PENDING) {
// NdisCompleteBindAdapter(Open->BindAdapterContext, Status,
// OpenErrorStatus);
// Open->Status = NDIS_STATUS_SUCCESS;
// }
//
// Initialize some media information
//
return;
}
//--------------------------------------------------------------------
//
// PacketUnbindAdapter - detach protocol from the NIC
//
//--------------------------------------------------------------------
VOID NDIS_API
PacketUnbindAdapter(OUT PNDIS_STATUS Status,
IN POPEN_INSTANCE Open,
IN POPEN_INSTANCE junk)
{
//
// clean up any pending I/O requests
//
PacketCleanUp(Status, Open);
//
// close the adapter
//
Debug_Out("PacketUnbindAdapter: calling NdisCloseAdapter\n");
NdisCloseAdapter(Status, Open->AdapterHandle);
Debug_Out("PacketUnbindAdapter: NdisCloseAdapter returned\n");
//
// Save status returned from NdisCloseAdapter for completion routine
//
Open->Status = *Status;
if (*Status != NDIS_STATUS_PENDING)
PacketUnbindAdapterComplete(Open, *Status);
Debug_Out("PacketUnbindAdapter: done\n");
return;
}
//--------------------------------------------------------------------
//
// PacketUnbindAdapterComplete - upcall on NdisCloseAdapter completion
//
//--------------------------------------------------------------------
VOID NDIS_API
PacketUnbindAdapterComplete(IN POPEN_INSTANCE Open,
IN NDIS_STATUS Status)
{
Debug_Out("CloseAdapterComplete: entered\n");
//
// If Open->Status == NDIS_STATUS_PENDING
// then we must complete the pended unbinding
//
if (Open->Status == NDIS_STATUS_PENDING) {
NdisCompleteUnbindAdapter(Open->BindAdapterContext, Status);
Open->Status = NDIS_STATUS_SUCCESS;
}
if (Status == NDIS_STATUS_SUCCESS) {
//
// Remove Adapter from global list
//
RemoveEntryList(&Open->ListElement);
//
// Free Memory
//
NdisFreeSpinLock(&Open->RequestSpinLock);
NdisFreeSpinLock(&Open->RcvQSpinLock);
NdisFreeSpinLock(&Open->ResetSpinLock);
NdisFreeBufferPool(Open->BufferPool);
NdisFreePacketPool(Open->PacketPool);
NdisFreeMemory(Open, sizeof(OPEN_INSTANCE), 0);
}
return;
}
//--------------------------------------------------------------------
//
// PacketCleanUp - cleanup before closing
//
//--------------------------------------------------------------------
VOID PacketCleanUp(PNDIS_STATUS Status,
POPEN_INSTANCE Open)
{
PLIST_ENTRY PacketListEntry;
PNDIS_PACKET pPacket;
//
// The open instance of the device is about to close
// We need to complete all pending I/O requests
// First we complete any pending read requests
//
NdisAcquireSpinLock(&Open->RcvQSpinLock);
while (!IsListEmpty(&Open->RcvList)) {
PacketListEntry = RemoveHeadList(&Open->RcvList);
pPacket = CONTAINING_RECORD(PacketListEntry, NDIS_PACKET, ProtocolReserved);
//
// complete normally
//
PacketTransferDataComplete(Open, pPacket, NDIS_STATUS_SUCCESS, 0);
}
NdisReleaseSpinLock(&Open->RcvQSpinLock);
// PacketReset(Status, Open);
return;
}
//--------------------------------------------------------------------
//
// PacketReset - reset the protocol
//
//--------------------------------------------------------------------
VOID PacketReset(PNDIS_STATUS pStatus,
POPEN_INSTANCE pOpen)
{
PLIST_ENTRY ResetListEntry;
//
// Acquire request element from list
//
NdisAllocateSpinLock(&pOpen->RequestSpinLock);
if (IsListEmpty(&pOpen->RequestList)) {
NdisReleaseSpinLock(&pOpen->RequestSpinLock);
*pStatus = NDIS_STATUS_RESOURCES;
Debug_Out("PacketReset: ERROR: RequestList empty\n");
return;
}
else {
ResetListEntry = RemoveHeadList(&pOpen->RequestList);
NdisReleaseSpinLock(&pOpen->RequestSpinLock);
}
//
// Insert Reset IRP into Request Queue
//
NdisAcquireSpinLock(&pOpen->ResetSpinLock);
InsertTailList(&pOpen->ResetIrpList, ResetListEntry);
NdisReleaseSpinLock(&pOpen->ResetSpinLock);
//
// Reset the adapter
//
NdisReset(pStatus, pOpen->AdapterHandle);
if (*pStatus != NDIS_STATUS_PENDING) {
PacketResetComplete(pOpen, *pStatus);
}
return;
}
//--------------------------------------------------------------------
//
// PacketResetComplete - upcall on reset completion
//
//--------------------------------------------------------------------
VOID NDIS_API PacketResetComplete(IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status)
{
POPEN_INSTANCE Open;
PLIST_ENTRY ResetListEntry;
Open = (POPEN_INSTANCE)ProtocolBindingContext;
//
// remove the reset request from the list
//
NdisAcquireSpinLock(&Open->ResetSpinLock);
if (IsListEmpty(&Open->ResetIrpList)) {
NdisReleaseSpinLock(&Open->ResetSpinLock);
Debug_Out("PacketResetComplete: ERROR: ResetIrpList empty\n");
return;
}
else {
ResetListEntry = RemoveHeadList(&Open->ResetIrpList);
NdisReleaseSpinLock(&Open->ResetSpinLock);
}
//
// Acquire request element from list
//
NdisAcquireSpinLock(&Open->RequestSpinLock);
InsertTailList(&Open->RequestList, ResetListEntry);
NdisReleaseSpinLock(&Open->RequestSpinLock);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -