📄 epacket.c
字号:
// Save status returned from NdisCloseAdapter for completion routine
Open->Status = *Status;
if (*Status != NDIS_STATUS_PENDING)
PacketUnbindAdapterComplete(Open, *Status);
}
///////////////////////////////////////////////////////////////////////////////
VOID NDIS_API PacketUnload()
{
// deregister the protocol, free remaining memory
// - called by NdisCloseAdapter when last adapter closed
NDIS_STATUS Status;
if (GlobalDeviceExtension != NULL) {
NdisDeregisterProtocol(&Status, GlobalDeviceExtension->NdisProtocolHandle);
if (Status == NDIS_STATUS_SUCCESS)
NdisFreeMemory(GlobalDeviceExtension, sizeof(DEVICE_EXTENSION), 0);
GlobalDeviceExtension = NULL;
}
}
///////////////////////////////////////////////////////////////////////////////
NTSTATUS NDIS_API DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
// initialiae the driver
NDIS_PROTOCOL_CHARACTERISTICS ProtocolChar;
NDIS_STRING ProtoName = NDIS_STRING_CONST("EPACKET");
NDIS_STATUS Status;
// Because the driver can be loaded once for each Netcard on the system,
// and because DriverEntry is called each time, we must ensure that
// initialization is performed only once.
if (GlobalDeviceExtension != NULL)
return NDIS_STATUS_SUCCESS;
NdisAllocateMemory((PVOID *)&GlobalDeviceExtension, sizeof(DEVICE_EXTENSION), 0, -1 );
if (GlobalDeviceExtension == NULL)
return NDIS_STATUS_RESOURCES;
NdisZeroMemory((UCHAR*)GlobalDeviceExtension, sizeof(DEVICE_EXTENSION));
NdisZeroMemory((UCHAR*)&ProtocolChar, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
ProtocolChar.MajorNdisVersion = 0x03;
ProtocolChar.MinorNdisVersion = 0x0a;
ProtocolChar.Reserved = 0;
ProtocolChar.OpenAdapterCompleteHandler = PacketBindAdapterComplete;
ProtocolChar.CloseAdapterCompleteHandler = PacketUnbindAdapterComplete;
ProtocolChar.SendCompleteHandler = PacketSendComplete;
ProtocolChar.TransferDataCompleteHandler = PacketTransferDataComplete;
ProtocolChar.ResetCompleteHandler = PacketResetComplete;
ProtocolChar.RequestCompleteHandler = PacketRequestComplete;
ProtocolChar.ReceiveHandler = PacketReceiveIndicate;
ProtocolChar.ReceiveCompleteHandler = PacketReceiveComplete;
ProtocolChar.StatusHandler = PacketStatus;
ProtocolChar.StatusCompleteHandler = PacketStatusComplete;
ProtocolChar.BindAdapterHandler = PacketBindAdapter;
ProtocolChar.UnbindAdapterHandler = PacketUnbindAdapter;
ProtocolChar.UnloadProtocolHandler = PacketUnload;
ProtocolChar.Name = ProtoName;
NdisRegisterProtocol(&Status,
&GlobalDeviceExtension->NdisProtocolHandle,
&ProtocolChar,
sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
if (Status != NDIS_STATUS_SUCCESS) {
NdisFreeMemory(GlobalDeviceExtension, sizeof(DEVICE_EXTENSION), 0);
return Status;
}
// initialize open list
InitializeListHead(&GlobalDeviceExtension->OpenList);
// initialize global device extension
GlobalDeviceExtension->DriverObject = DriverObject;
return Status;
}
///////////////////////////////////////////////////////////////////////////////
POPEN_INSTANCE GetOpen(DWORD handle)
{
// return a specified Open Instance
PLIST_ENTRY pHead = &GlobalDeviceExtension->OpenList;
PLIST_ENTRY pTemp;
POPEN_INSTANCE Open;
if (GlobalDeviceExtension == NULL)
return NULL;
// search the list for the Open Instance containing the specified handle
for (pTemp = pHead->Flink; pTemp != pHead; pTemp = pTemp->Flink) {
Open = CONTAINING_RECORD(pTemp, OPEN_INSTANCE, ListElement);
if (Open && Open->hDevice == handle)
return Open;
}
return NULL; // just in case
}
///////////////////////////////////////////////////////////////////////////////
VOID PacketAllocatePacketBuffer(PNDIS_STATUS pStatus,
POPEN_INSTANCE pOpen,
PNDIS_PACKET *ppPacket,
PDIOCPARAMETERS pDiocParms,
DWORD FunctionCode )
{
// allocate a buffer for reading/writing
PNDIS_BUFFER pNdisBuffer;
PNDIS_PACKET pPacket;
// Try to get a packet from our list of free ones
NdisAllocatePacket(pStatus, ppPacket, pOpen->PacketPool);
if (*pStatus != NDIS_STATUS_SUCCESS) {
*(DWORD *)(pDiocParms->lpcbBytesReturned) = 0;
return;
}
pPacket = *ppPacket;
// Buffers used asynchronously must be page locked
switch (FunctionCode) {
case IOCTL_EPACKET_READ:
RESERVED(pPacket)->lpBuffer = (PVOID)PacketPageLock(pDiocParms->lpvOutBuffer, pDiocParms->cbOutBuffer);
RESERVED(pPacket)->cbBuffer = pDiocParms->cbOutBuffer;
break;
case IOCTL_EPACKET_WRITE:
RESERVED(pPacket)->lpBuffer = (PVOID)PacketPageLock(pDiocParms->lpvInBuffer, pDiocParms->cbInBuffer);
RESERVED(pPacket)->cbBuffer = pDiocParms->cbInBuffer;
break;
default:
// recycle the packet
NdisReinitializePacket(pPacket);
// Put the packet on the free queue
NdisFreePacket(pPacket);
*(DWORD *)(pDiocParms->lpcbBytesReturned) = 0;
*pStatus = NDIS_STATUS_NOT_ACCEPTED;
return;
}
RESERVED(pPacket)->lpcbBytesReturned = (PVOID)PacketPageLock(pDiocParms->lpcbBytesReturned, sizeof(DWORD));
RESERVED(pPacket)->lpoOverlapped = (PVOID)PacketPageLock(pDiocParms->lpoOverlapped, sizeof(OVERLAPPED));
RESERVED(pPacket)->hDevice = pDiocParms->hDevice;
RESERVED(pPacket)->tagProcess = pDiocParms->tagProcess;
switch (FunctionCode) {
case IOCTL_EPACKET_READ:
NdisAllocateBuffer(pStatus,
&pNdisBuffer,
pOpen->BufferPool,
(PVOID)(RESERVED(pPacket)->lpBuffer + ETHERNET_HEADER_LENGTH),
pDiocParms->cbOutBuffer);
break;
case IOCTL_EPACKET_WRITE:
NdisAllocateBuffer(pStatus,
&pNdisBuffer,
pOpen->BufferPool,
(PVOID)RESERVED(pPacket)->lpBuffer,
pDiocParms->cbInBuffer);
break;
}
if (*pStatus == NDIS_STATUS_SUCCESS)
NdisChainBufferAtFront(pPacket, pNdisBuffer); // Attach buffer to Packet
else {
NdisReinitializePacket(pPacket); // recycle the packet
NdisFreePacket(pPacket); // Put the packet on the free queue
*(DWORD *)(pDiocParms->lpcbBytesReturned) = 0;
}
}
///////////////////////////////////////////////////////////////////////////////
DWORD PacketRead(POPEN_INSTANCE Open,
DWORD dwDDB,
DWORD hDevice,
PDIOCPARAMETERS pDiocParms)
{
// read a packet
NDIS_STATUS Status;
PNDIS_PACKET pPacket;
// Check that the buffer can hold a max length Ethernet packet
if (pDiocParms->cbOutBuffer < ETHERNET_PACKET_LENGTH) {
*(DWORD *)(pDiocParms->lpcbBytesReturned) = 0; // Need bigger buffer
return NDIS_STATUS_SUCCESS;
}
PacketAllocatePacketBuffer(&Status, Open, &pPacket, pDiocParms, IOCTL_EPACKET_READ);
if (Status == NDIS_STATUS_SUCCESS) {
// Put this packet in a list of pending reads.
// The receive indication handler will attempt to remove packets
// from this list for use in transfer data calls
NdisAcquireSpinLock(&Open->RcvQSpinLock); // fixed 6.11.97
InsertTailList(&Open->RcvList, &RESERVED(pPacket)->ListElement);
NdisReleaseSpinLock(&Open->RcvQSpinLock);
}
return -1; // This will make DeviceIOControl return ERROR_IO_PENDING
}
///////////////////////////////////////////////////////////////////////////////
DWORD PacketWrite(POPEN_INSTANCE Open,
DWORD dwDDB,
DWORD hDevice,
PDIOCPARAMETERS pDiocParms)
{
// write a packet
PNDIS_PACKET pPacket;
NDIS_STATUS Status;
PacketAllocatePacketBuffer(&Status, Open, &pPacket, pDiocParms, IOCTL_EPACKET_WRITE);
if (Status != NDIS_STATUS_SUCCESS)
return 0; // This will return immediately with no data written
// Call the MAC
NdisSend(&Status, Open->AdapterHandle, pPacket);
if (Status != NDIS_STATUS_PENDING) {
// The send didn't pend so call the completion handler now
PacketSendComplete(Open, pPacket, Status);
}
return(-1); // This will make DeviceIOControl return ERROR_IO_PENDING
}
///////////////////////////////////////////////////////////////////////////////
DWORD _stdcall PacketIOControl(DWORD dwService,
DWORD dwDDB,
DWORD hDevice,
PDIOCPARAMETERS pDiocParms)
{
// called from applications
POPEN_INSTANCE Open;
NDIS_STATUS Status;
UCHAR AdapterBuffer[5];
NDIS_STRING AdapterName = NDIS_STRING_CONST(AdapterBuffer);
switch (dwService) {
case DIOC_OPEN:
return NDIS_STATUS_SUCCESS;
case DIOC_CLOSEHANDLE:
if ((Open = GetOpen(hDevice)) != NULL)
PacketUnbindAdapter(&Status, Open, NULL);
return NDIS_STATUS_SUCCESS;
case IOCTL_EPACKET_VERSION:
if (pDiocParms->cbOutBuffer < 2)
*(DWORD *)(pDiocParms->lpcbBytesReturned) = 0;
else {
((BYTE *)pDiocParms->lpvOutBuffer)[0] = MAJOR_VERSION;
((BYTE *)pDiocParms->lpvOutBuffer)[1] = MINOR_VERSION;
*(DWORD *)pDiocParms->lpcbBytesReturned = 2;
}
return NDIS_STATUS_SUCCESS;
case IOCTL_EPACKET_BIND:
memcpy(AdapterName.Buffer, (BYTE *)pDiocParms->lpvInBuffer,
min(strlen((char *)pDiocParms->lpvInBuffer), sizeof(AdapterBuffer)-1));
AdapterName.Buffer[sizeof(AdapterBuffer)-1] = '\0';
PacketBindAdapter(&Status,
GlobalDeviceExtension->NdisProtocolHandle,
&AdapterName,
(PVOID)hDevice, /* special */
NULL);
// Note: If the above usage of the 4'th arg to PacketBindAdapter
// causes problems, use a global variable instead.
if (Status == NDIS_STATUS_SUCCESS || Status == NDIS_STATUS_PENDING) {
*(DWORD *)pDiocParms->lpcbBytesReturned = 1;
return NDIS_STATUS_SUCCESS;
}
break;
case IOCTL_EPACKET_SET_OID:
case IOCTL_EPACKET_QUERY_OID:
if ((Open = GetOpen(hDevice)) != NULL)
return PacketRequest(Open, dwService, dwDDB, hDevice, pDiocParms);
break;
case IOCTL_EPACKET_READ:
if ((Open = GetOpen(hDevice)) != NULL)
return PacketRead(Open, dwDDB, hDevice, pDiocParms);
break;
case IOCTL_EPACKET_WRITE:
if ((Open = GetOpen(hDevice)) != NULL)
return PacketWrite(Open, dwDDB, hDevice, pDiocParms);
break;
}
*(DWORD *)pDiocParms->lpcbBytesReturned = 0;
return NDIS_STATUS_SUCCESS;
}
// End of File ////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -