От:
Snoobot
Дата: 13.01.04 18:38
Оценка:
Почти ничего не знаю в области, о которой хочу задать вопрос, надеюсь на подсказку
куда копать (пока теряюсь — то ли дело в правах, то ли в драйверах или в сетевом стеке).
Есть унаследованный kernel mode driver, который не запускается в XP Prof с сообщением
"The system encountered the following error while attempting to start the service
A device attached to the system is not functioning."
В NT4 и Win2K(Prof,Server) успешно работает.
О назначении: предоставляет принимать/передавать данные через сетевую карту
исключая обычный сетевой стек(используется свой) используя в дальнейшем CreateFile("\\\\.\\nh_lan",...), ReadFile, WriteFile
#include "ndis.h" //from ddk
#define MarkPending(IrpSp) ( IrpSp->Control |= SL_PENDING_RETURNED )
#define UnMarkPending(IrpSp) ( IrpSp->Control &= ~SL_PENDING_RETURNED )
#ifndef CTL_CODE
// From Windows NT 3.51 DDK inc\ntddk.h
//
// Macro definition for defining IOCTL and FSCTL function control codes. Note
// that function codes 0-2047 are reserved for Microsoft Corporation, and
// 2048-4095 are reserved for customers.
//
#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
(DWORD) ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)
//
// Define the method codes for how buffers are passed for I/O and FS controls
//
#define METHOD_BUFFERED 0
#define METHOD_IN_DIRECT 1
#define METHOD_OUT_DIRECT 2
#define METHOD_NEITHER 3
//
// Define the access check value for any access
//
//
// The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in
// ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these
// constants *MUST* always be in sync.
//
#define FILE_ANY_ACCESS 0
#define FILE_READ_ACCESS ( 0x0001 ) // file & pipe
#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe
#endif
#define FILE_DEVICE_PROTOCOL 0x8000
#define NDISSUPP_SetFilter CTL_CODE(FILE_DEVICE_PROTOCOL, 0 , METHOD_BUFFERED, FILE_ANY_ACCESS)
#define NDISSUPP_WritePacket CTL_CODE(FILE_DEVICE_PROTOCOL, 1 , METHOD_BUFFERED, FILE_ANY_ACCESS)
#define NDISSUPP_ReadPacket CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS)
#define NDISSUPP_GetAddress CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS)
#define NDISSUPP_GetNAdapters CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS)
#define NDISSUPP_GetAdapterName CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS)
#define NDISSUPP_InitAdapter CTL_CODE(FILE_DEVICE_PROTOCOL, 8 , METHOD_BUFFERED, FILE_ANY_ACCESS)
#define NDISSUPP_OpenAdapter CTL_CODE(FILE_DEVICE_PROTOCOL, 9 , METHOD_BUFFERED, FILE_ANY_ACCESS)
PVOID Malloc (UINT size);
void Free (PVOID pUsrBuf);
typedef struct
{
NDIS_HANDLE AdapterHandle;
UCHAR physAddress [6];
NDIS_HANDLE PacketPool;
KSPIN_LOCK RcvQSpinLock;
LIST_ENTRY RcvList;
PIRP pOpenIrp;
PIRP pCloseIrp;
NDIS_HANDLE BindContext;
PDEVICE_OBJECT pDeviceObject;
} OPEN_INSTANCE, *POPEN_INSTANCE;
//extern OPEN_INSTANCE *pInstance;
typedef struct
{
LIST_ENTRY ListElement;
PIRP Irp;
PMDL pMdl;
} PACKET_RESERVED, *PPACKET_RESERVED;
typedef struct
{
NDIS_REQUEST request;
PIRP pIrp;
} REQUEST_RESERVED, *PREQUEST_RESERVED;
typedef struct
{
NDIS_HANDLE NdisProtocolHandle;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
#define offset(_p,type) (ULONG)(&(((type*)0)->_p))
#define ETHERNET_HEADER_LENGTH 14
VOID LanOpenAdapterComplete
(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN NDIS_STATUS OpenErrorStatus
);
VOID LanCloseAdapterComplete
(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
);
NDIS_STATUS LanReceiveIndicate
(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE MacReceiveContext,
IN PVOID HeaderBuffer,
IN UINT HeaderBufferSize,
IN PVOID LookAheadBuffer,
IN UINT LookaheadBufferSize,
IN UINT PacketSize
);
VOID LanReceiveComplete
(
IN NDIS_HANDLE ProtocolBindingContext
);
VOID LanRequestComplete
(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_REQUEST pRequest,
IN NDIS_STATUS Status
);
VOID LanSendComplete
(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET pPacket,
IN NDIS_STATUS Status
);
VOID LanResetComplete
(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
);
VOID LanStatus
(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN PVOID StatusBuffer,
IN UINT StatusBufferSize
);
VOID LanStatusComplete
(
IN NDIS_HANDLE ProtocolBindingContext
);
VOID LanTransferDataComplete
(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet,
IN NDIS_STATUS Status,
IN UINT BytesTransferred
);
INT LanReceivePacket
(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet
);
NTSTATUS LanCleanup
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP FlushIrp
);
VOID LanUnload
(
IN PDRIVER_OBJECT DriverObject
);
NTSTATUS LanOpen
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS LanClose
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS LanRead
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS LanWrite
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS LanIoControl
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NDIS_STATUS CompleteIrp (IRP * pIrp, NDIS_STATUS Status);
NTSTATUS LanCreateSymbolicLink
(
IN PUNICODE_STRING DeviceName,
IN BOOLEAN Create
);
NTSTATUS DriverEntry
(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
PDEVICE_EXTENSION pDeviceExtension;
PDEVICE_OBJECT pDeviceObject;
NDIS_PROTOCOL_CHARACTERISTICS ProtocolChar;
UNICODE_STRING UnicodeDeviceName;
NTSTATUS Status;
NDIS_STRING ProtoName = NDIS_STRING_CONST ("INT LAN support for Router");
NDIS_HANDLE NdisProtocolHandle;
#ifdef WIN2K
RTL_OSVERSIONINFOW ov;
ov.dwOSVersionInfoSize = sizeof (ov);
RtlGetVersion (&ov);
if (ov.dwMajorVersion != 5)
return STATUS_UNSUCCESSFUL;
#endif
RtlZeroMemory (&ProtocolChar, sizeof (NDIS_PROTOCOL_CHARACTERISTICS));
ProtocolChar.MajorNdisVersion = 4;
ProtocolChar.MinorNdisVersion = 0;
ProtocolChar.Reserved = 0;
ProtocolChar.OpenAdapterCompleteHandler = LanOpenAdapterComplete;
ProtocolChar.CloseAdapterCompleteHandler = LanCloseAdapterComplete;
ProtocolChar.SendCompleteHandler = LanSendComplete;
ProtocolChar.TransferDataCompleteHandler = LanTransferDataComplete;
ProtocolChar.ResetCompleteHandler = LanResetComplete;
ProtocolChar.RequestCompleteHandler = LanRequestComplete;
ProtocolChar.ReceiveHandler = LanReceiveIndicate;
ProtocolChar.ReceiveCompleteHandler = LanReceiveComplete;
ProtocolChar.StatusHandler = LanStatus;
ProtocolChar.StatusCompleteHandler = LanStatusComplete;
ProtocolChar.Name = ProtoName;
ProtocolChar.ReceivePacketHandler = LanReceivePacket;
ProtocolChar.BindAdapterHandler = 0;
ProtocolChar.UnbindAdapterHandler = 0;
// ProtocolChar.TranslateHandler = 0;
ProtocolChar.UnloadHandler = 0;
NdisRegisterProtocol
(
&Status,
&NdisProtocolHandle,
&ProtocolChar,
sizeof (NDIS_PROTOCOL_CHARACTERISTICS)
);
if (Status != NDIS_STATUS_SUCCESS)
{
return STATUS_UNSUCCESSFUL;
}
//
// Set up the device driver entry points.
//
DriverObject->MajorFunction [IRP_MJ_CREATE] = LanOpen;
DriverObject->MajorFunction [IRP_MJ_CLOSE] = LanClose;
DriverObject->MajorFunction [IRP_MJ_READ] = LanRead;
DriverObject->MajorFunction [IRP_MJ_WRITE] = LanWrite;
DriverObject->MajorFunction [IRP_MJ_CLEANUP] = LanCleanup;
DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = LanIoControl;
DriverObject->DriverUnload = LanUnload;
RtlInitUnicodeString
(
&UnicodeDeviceName,
L"\\Device\\NH_LAN"
);
//
// Create the device object
//
if ((IoCreateDevice (DriverObject, sizeof (DEVICE_EXTENSION),
&UnicodeDeviceName,
FILE_DEVICE_PROTOCOL, 0, FALSE, &pDeviceObject) !=
STATUS_SUCCESS) || (LanCreateSymbolicLink (&UnicodeDeviceName, TRUE) !=
STATUS_SUCCESS))
{
NdisDeregisterProtocol (&Status, NdisProtocolHandle);
return STATUS_UNSUCCESSFUL;
}
pDeviceObject->Flags |= DO_DIRECT_IO;
pDeviceExtension = (PDEVICE_EXTENSION) pDeviceObject->DeviceExtension;
pDeviceExtension->NdisProtocolHandle = NdisProtocolHandle;
return STATUS_SUCCESS;
}
VOID LanUnload
(
IN PDRIVER_OBJECT DriverObject
)
{
NDIS_STATUS Status;
PDEVICE_OBJECT pDeviceObject = DriverObject->DeviceObject;
PDEVICE_EXTENSION pDE = (PDEVICE_EXTENSION) pDeviceObject->DeviceExtension;
LanCreateSymbolicLink (NULL, FALSE);
IoDeleteDevice (pDeviceObject);
NdisDeregisterProtocol
(
&Status, pDE->NdisProtocolHandle
);
}
VOID LanRequestComplete
(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_REQUEST pRequest,
IN NDIS_STATUS Status
)
{
REQUEST_RESERVED * pRR = (REQUEST_RESERVED *)
(((UCHAR *) pRequest) — offset (request, REQUEST_RESERVED));
CompleteIrp (pRR->pIrp, (Status == NDIS_STATUS_SUCCESS) ?
STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
Free (pRR);
}
VOID LanStatus
(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN PVOID StatusBuffer,
IN UINT StatusBufferSize
)
{
}
VOID LanStatusComplete
(
IN NDIS_HANDLE ProtocolBindingContext
)
{
}
NTSTATUS LanCreateSymbolicLink
(
IN PUNICODE_STRING DeviceName,
IN BOOLEAN Create
)
{
UNICODE_STRING UnicodeDosDeviceName;
RtlInitUnicodeString
(
&UnicodeDosDeviceName,
L"\\DosDevices\\NH_LAN"
);
return Create ? IoCreateSymbolicLink (&UnicodeDosDeviceName, DeviceName)
: IoDeleteSymbolicLink (&UnicodeDosDeviceName);
}
NDIS_STATUS CompleteIrp (IRP * pIrp, NDIS_STATUS Status)
{
pIrp->IoStatus.Status = Status;
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
return Status;
}
typedef struct {
ULONG length;
} MemoryBlock;
PVOID Malloc (UINT size) {
NDIS_PHYSICAL_ADDRESS pha = {-1, -1};
MemoryBlock * pBuf;
NDIS_STATUS Status = NdisAllocateMemory
(&pBuf, size + sizeof (MemoryBlock), NDIS_MEMORY_NONCACHED, pha);
pBuf->length = size + sizeof (MemoryBlock);
return (Status == NDIS_STATUS_SUCCESS) ? (PVOID) (pBuf + 1) : 0;
}
void Free (PVOID pUsrBuf) {
MemoryBlock * pBuf = ((MemoryBlock *) pUsrBuf) — 1;
NdisFreeMemory (pBuf, pBuf->length, NDIS_MEMORY_NONCACHED);
}
NDIS_STATUS MakeRequest (REQUEST_RESERVED * pRequest, PIRP pIrp,
PIO_STACK_LOCATION pIrpSp, POPEN_INSTANCE pInstance);
NTSTATUS LanIoControl
(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
{
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation (pIrp);
POPEN_INSTANCE pInstance = IrpSp->FileObject->FsContext;
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
{
case NDISSUPP_GetAddress:
{
UINT len = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
if (len != 6)
{
return CompleteIrp (pIrp, STATUS_UNSUCCESSFUL);
}
RtlCopyMemory
(
pIrp->AssociatedIrp.SystemBuffer,
pInstance->physAddress,
6
);
pIrp->IoStatus.Information = 6;
return CompleteIrp (pIrp, STATUS_SUCCESS);
}
case NDISSUPP_OpenAdapter:
{
NDIS_STATUS Status;
NDIS_STATUS ErrorStatus;
UINT Medium;
NDIS_MEDIUM MediumArray = NdisMedium802_3;
UNICODE_STRING MacDriverName;
PDEVICE_EXTENSION pDeviceExtension = (PDEVICE_EXTENSION)
pDeviceObject->DeviceExtension;
PUSHORT p = (PUSHORT) pIrp->AssociatedIrp.SystemBuffer;
UINT len = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if ((len % 2) || (len == 0) || (p [len/2 — 1] != 0))
{
return CompleteIrp (pIrp, STATUS_UNSUCCESSFUL);
}
RtlInitUnicodeString
(
&MacDriverName,
(PWSTR) pIrp->AssociatedIrp.SystemBuffer
);
MarkPending (IrpSp);
pInstance->pOpenIrp = pIrp;
NdisOpenAdapter
(
&Status,
&ErrorStatus,
&pInstance->AdapterHandle,
&Medium,
&MediumArray,
1,
pDeviceExtension->NdisProtocolHandle,
pInstance->BindContext,
&MacDriverName,
0,
NULL
);
if (Status != NDIS_STATUS_PENDING) {
UnMarkPending (IrpSp);
LanOpenAdapterComplete (
pInstance->BindContext,
Status,
ErrorStatus
);
return (Status == NDIS_STATUS_SUCCESS) ?
STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
return STATUS_PENDING;
}
case NDISSUPP_InitAdapter:
{
REQUEST_RESERVED * pRequest =
(REQUEST_RESERVED *) Malloc (sizeof (REQUEST_RESERVED));
if (pRequest == 0) {
return CompleteIrp (pIrp, STATUS_UNSUCCESSFUL);
}
pRequest->request.RequestType = NdisRequestQueryInformation;
pRequest->request.DATA.QUERY_INFORMATION.Oid = 0x01010102;
pRequest->request.DATA.QUERY_INFORMATION.InformationBuffer =
pInstance->physAddress;
pRequest->request.DATA.QUERY_INFORMATION.InformationBufferLength = 6;
return MakeRequest (pRequest, pIrp, IrpSp, pInstance);
}
case NDISSUPP_SetFilter:
{
static ULONG filter =
NDIS_PACKET_TYPE_BROADCAST |
NDIS_PACKET_TYPE_DIRECTED |
NDIS_PACKET_TYPE_ALL_MULTICAST;
REQUEST_RESERVED * pRequest =
(REQUEST_RESERVED *) Malloc (sizeof (REQUEST_RESERVED));
if (pRequest == 0) {
return CompleteIrp (pIrp, STATUS_UNSUCCESSFUL);
}
pRequest->request.RequestType = NdisRequestSetInformation;
pRequest->request.DATA.SET_INFORMATION.Oid = 0x0001010E;
pRequest->request.DATA.SET_INFORMATION.InformationBuffer = &filter;
pRequest->request.DATA.SET_INFORMATION.InformationBufferLength = 4;
return MakeRequest (pRequest, pIrp, IrpSp, pInstance);
}
default:
{
return CompleteIrp (pIrp, STATUS_UNSUCCESSFUL);
}
}
}
NDIS_STATUS MakeRequest (REQUEST_RESERVED * pRequest, PIRP pIrp,
PIO_STACK_LOCATION pIrpSp, POPEN_INSTANCE pInstance)
{
NDIS_STATUS Status;
pRequest->pIrp = pIrp;
MarkPending (pIrpSp);
NdisRequest (&Status, pInstance->AdapterHandle, &pRequest->request);
if (Status != NDIS_STATUS_PENDING)
{
UnMarkPending (pIrpSp);
LanRequestComplete
(
pInstance->BindContext,
&pRequest->request,
Status
);
return (Status == NDIS_STATUS_SUCCESS) ?
STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
return STATUS_PENDING;
}
NTSTATUS LanOpen
(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
{
NDIS_STATUS Status;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation (pIrp);
POPEN_INSTANCE pInstance = ExAllocatePool
(NonPagedPool, sizeof (OPEN_INSTANCE));
if (pInstance == 0)
{
return STATUS_UNSUCCESSFUL;
}
RtlZeroMemory (pInstance, sizeof (OPEN_INSTANCE));
pInstance->BindContext = (NDIS_HANDLE) pInstance;
IrpSp->FileObject->FsContext = pInstance;
NdisAllocatePacketPool
(
&Status,
&pInstance->PacketPool,
50,
sizeof (PACKET_RESERVED)
);
if (Status != NDIS_STATUS_SUCCESS)
{
return CompleteIrp (pIrp, STATUS_INSUFFICIENT_RESOURCES);
}
KeInitializeSpinLock (&pInstance->RcvQSpinLock);
InitializeListHead (&pInstance->RcvList);
return CompleteIrp (pIrp, STATUS_SUCCESS);
}
VOID LanOpenAdapterComplete
(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN NDIS_STATUS OpenErrorStatus
)
{
POPEN_INSTANCE pInstance = (POPEN_INSTANCE) ProtocolBindingContext;
CompleteIrp (pInstance->pOpenIrp, (Status == NDIS_STATUS_SUCCESS) ?
STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
}
NTSTATUS LanClose
(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
{
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation (pIrp);
POPEN_INSTANCE pInstance = IrpSp->FileObject->FsContext;
NDIS_STATUS Status;
pInstance->pCloseIrp = pIrp;
if (pInstance->AdapterHandle)
{
MarkPending (IrpSp);
NdisCloseAdapter
(
&Status,
pInstance->AdapterHandle
);
if (Status == NDIS_STATUS_PENDING)
return STATUS_PENDING;
UnMarkPending (IrpSp);
}
LanCloseAdapterComplete
(
pInstance->BindContext,
Status
);
return (Status == NDIS_STATUS_SUCCESS) ?
STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
VOID LanCloseAdapterComplete
(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
)
{
POPEN_INSTANCE pInstance = (POPEN_INSTANCE) ProtocolBindingContext;
CompleteIrp (pInstance->pCloseIrp, (Status == NDIS_STATUS_SUCCESS) ?
STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
NdisFreePacketPool (pInstance->PacketPool);
ExFreePool (pInstance);
}
NTSTATUS LanCleanup
(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
{
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation (pIrp);
POPEN_INSTANCE pInstance = IrpSp->FileObject->FsContext;
PLIST_ENTRY PacketListEntry;
KIRQL saveIrql;
//
// The open instance of the device is about to close
// We need to complete all pending Irp's
//
IoAcquireCancelSpinLock (&saveIrql);
while ((PacketListEntry = ExInterlockedRemoveHeadList
(
&pInstance->RcvList,
&pInstance->RcvQSpinLock
)
) != NULL)
{
PNDIS_PACKET pPacket = (NDIS_PACKET *)
(((UCHAR *) PacketListEntry) —
offset (ProtocolReserved, NDIS_PACKET));
PIRP curIrp = ((PPACKET_RESERVED) (pPacket->ProtocolReserved))->Irp;
PMDL pMdl = ((PPACKET_RESERVED) (pPacket->ProtocolReserved))->pMdl;
if (pMdl) IoFreeMdl (pMdl);
NdisFreePacket (pPacket);
IoSetCancelRoutine (curIrp, NULL);
curIrp->IoStatus.Information = 0;
CompleteIrp (curIrp, STATUS_CANCELLED);
}
IoReleaseCancelSpinLock (saveIrql);
return CompleteIrp (pIrp, STATUS_SUCCESS);
}
VOID LanResetComplete
(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
)
{
}
void LanCancelRoutine
(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
{
KIRQL saveIrql;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation (pIrp);
POPEN_INSTANCE pInstance = IrpSp->FileObject->FsContext;
PLIST_ENTRY PacketListEntry = pInstance->RcvList.Flink;
KeAcquireSpinLock (&pInstance->RcvQSpinLock, &saveIrql);
while (PacketListEntry != &pInstance->RcvList)
{
PNDIS_PACKET pPacket = (NDIS_PACKET *)
(((UCHAR *) PacketListEntry) —
offset (ProtocolReserved, NDIS_PACKET));
if (pIrp == ((PPACKET_RESERVED) (pPacket->ProtocolReserved))->Irp)
{
PMDL pMdl = ((PPACKET_RESERVED) (pPacket->ProtocolReserved))->pMdl;
RemoveEntryList (PacketListEntry);
IoSetCancelRoutine (pIrp, 0);
KeReleaseSpinLock (&pInstance->RcvQSpinLock, saveIrql);
IoReleaseCancelSpinLock (pIrp->CancelIrql);
if (pMdl) IoFreeMdl (pMdl);
NdisFreePacket (pPacket);
pIrp->IoStatus.Information = 0;
CompleteIrp (pIrp, STATUS_CANCELLED);
return;
}
PacketListEntry = PacketListEntry->Flink;
}
KeReleaseSpinLock (&pInstance->RcvQSpinLock, saveIrql);
IoReleaseCancelSpinLock (pIrp->CancelIrql);
}
NTSTATUS LanRead
(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
{
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation (pIrp);
POPEN_INSTANCE pInstance = IrpSp->FileObject->FsContext;
PNDIS_PACKET pPacket;
NDIS_STATUS Status;
NdisAllocatePacket
(
&Status,
&pPacket,
pInstance->PacketPool
);
if (Status != NDIS_STATUS_SUCCESS)
{
return CompleteIrp (pIrp, STATUS_UNSUCCESSFUL);
}
((PPACKET_RESERVED) (pPacket->ProtocolReserved))->Irp = pIrp;
((PPACKET_RESERVED) (pPacket->ProtocolReserved))->pMdl = 0;
MarkPending (IrpSp);
IoSetCancelRoutine (pIrp, LanCancelRoutine);
ExInterlockedInsertTailList
(
&pInstance->RcvList,
&((PPACKET_RESERVED)(pPacket->ProtocolReserved))->ListElement,
&pInstance->RcvQSpinLock
);
return STATUS_PENDING;
}
NDIS_STATUS LanReceiveIndicate
(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE MacReceiveContext,
IN PVOID HeaderBuffer,
IN UINT HeaderBufferSize,
IN PVOID LookAheadBuffer,
IN UINT LookaheadBufferSize,
IN UINT PacketSize
)
{
PIRP pIrp;
PLIST_ENTRY PacketListEntry;
PNDIS_PACKET pPacket;
ULONG SizeToTransfer;
NDIS_STATUS Status;
UINT BytesTransfered;
ULONG BufferLength;
PUCHAR pUserBuffer;
PIO_STACK_LOCATION IrpSp;
POPEN_INSTANCE pInstance = (POPEN_INSTANCE) ProtocolBindingContext;
if (HeaderBufferSize != ETHERNET_HEADER_LENGTH)
{
return NDIS_STATUS_NOT_RECOGNIZED;
}
/*
if (RtlCompareMemory (pInstance->physAddress,
((PUCHAR) HeaderBuffer) + 6, 6) == 6)
return NDIS_STATUS_NOT_RECOGNIZED;
*/
PacketListEntry = ExInterlockedRemoveHeadList
(
&pInstance->RcvList,
&pInstance->RcvQSpinLock
);
if (PacketListEntry == NULL)
return NDIS_STATUS_RESOURCES;
pPacket = (NDIS_PACKET *)
(((UCHAR *) PacketListEntry) — offset (ListElement, PACKET_RESERVED) —
offset (ProtocolReserved, NDIS_PACKET));
pIrp = ((PPACKET_RESERVED)(pPacket->ProtocolReserved))->Irp;
IoSetCancelRoutine (pIrp, NULL);
IrpSp = IoGetCurrentIrpStackLocation (pIrp);
pUserBuffer = MmGetSystemAddressForMdl (pIrp->MdlAddress);
//
// This is the length of our partial MDL
//
BufferLength = IrpSp->Parameters.Read.Length — ETHERNET_HEADER_LENGTH;
//
// Find out how much to transfer
//
SizeToTransfer = (PacketSize < BufferLength) ?
PacketSize : BufferLength;
//
// copy the ethernet header into the actual readbuffer
//
RtlCopyMemory
(
pUserBuffer,
HeaderBuffer,
ETHERNET_HEADER_LENGTH
);
if (SizeToTransfer <= LookaheadBufferSize)
{
RtlCopyMemory
(
pUserBuffer + ETHERNET_HEADER_LENGTH,
LookAheadBuffer,
SizeToTransfer
);
Status = NDIS_STATUS_SUCCESS;
BytesTransfered = SizeToTransfer;
}
else
{
PMDL pMdl = IoAllocateMdl
(
MmGetMdlVirtualAddress (pIrp->MdlAddress),
MmGetMdlByteCount (pIrp->MdlAddress),
FALSE,
FALSE,
NULL
);
if (pMdl) {
IoBuildPartialMdl
(
pIrp->MdlAddress,
pMdl,
((PUCHAR)MmGetMdlVirtualAddress (pIrp->MdlAddress)) +
ETHERNET_HEADER_LENGTH,
0
);
NdisChainBufferAtFront (pPacket, pMdl);
((PPACKET_RESERVED) (pPacket->ProtocolReserved))->pMdl = pMdl;
NdisTransferData
(
&Status,
pInstance->AdapterHandle,
MacReceiveContext,
0,
SizeToTransfer,
pPacket,
&BytesTransfered
)
} else {
Status = NDIS_STATUS_RESOURCES;
}
}
switch (Status)
{
case NDIS_STATUS_SUCCESS: // received packet
Status = (BytesTransfered == SizeToTransfer) ?
NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE;
break;
case NDIS_STATUS_PENDING:
return NDIS_STATUS_SUCCESS;
default: // something broke; certainly we'll never get NdisTransferData
// asynch completion with this error status...
Status = NDIS_STATUS_FAILURE;
break;
}
LanTransferDataComplete (pInstance->BindContext,
pPacket, Status, BytesTransfered);
return NDIS_STATUS_SUCCESS;
}
VOID LanTransferDataComplete
(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET pPacket,
IN NDIS_STATUS Status,
IN UINT BytesTransfered
)
{
PIRP Irp = ((PPACKET_RESERVED) (pPacket->ProtocolReserved))->Irp;
PMDL pMdl = ((PPACKET_RESERVED) (pPacket->ProtocolReserved))->pMdl;
if (pMdl) IoFreeMdl (pMdl);
NdisFreePacket (pPacket);
if (Status == NDIS_STATUS_SUCCESS)
{
Irp->IoStatus.Information = BytesTransfered + ETHERNET_HEADER_LENGTH;
CompleteIrp (Irp, STATUS_SUCCESS);
}
else
{
Irp->IoStatus.Information = 0;
CompleteIrp (Irp, STATUS_UNSUCCESSFUL);
}
}
VOID LanReceiveComplete
(
IN NDIS_HANDLE ProtocolBindingContext
)
{
}
INT LanReceivePacket
(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet
)
{
UINT bytesTransfered = 0, BufferLength;
PLIST_ENTRY PacketListEntry;
PNDIS_PACKET pPacket;
// PUCHAR pUserBuffer;
NDIS_STATUS Status = STATUS_SUCCESS;
PIRP pIrp;
PIO_STACK_LOCATION IrpSp;
POPEN_INSTANCE pInstance = (POPEN_INSTANCE) ProtocolBindingContext;
PacketListEntry = ExInterlockedRemoveHeadList
(
&pInstance->RcvList,
&pInstance->RcvQSpinLock
);
if (PacketListEntry == NULL)
return 0;
pPacket = (NDIS_PACKET *)
(((UCHAR *) PacketListEntry) — offset (ListElement, PACKET_RESERVED) —
offset (ProtocolReserved, NDIS_PACKET));
pIrp = ((PPACKET_RESERVED)(pPacket->ProtocolReserved))->Irp;
IrpSp = IoGetCurrentIrpStackLocation (pIrp);
IoSetCancelRoutine (pIrp, NULL);
NdisChainBufferAtFront (pPacket, pIrp->MdlAddress);
BufferLength = IrpSp->Parameters.Read.Length;
// pUserBuffer = MmGetSystemAddressForMdl (pIrp->MdlAddress);
// {
// PVOID virtualAddress;
// PNDIS_BUFFER firstBuffer, nextBuffer;
// ULONG offset = 0;
//
// NdisQueryPacket (Packet, NULL, NULL, &firstBuffer, &bytesTransfered);
// if (bytesTransfered > BufferLength) {
// NdisFreePacket (pPacket);
// pIrp->IoStatus.Information = 0;
// CompleteIrp (pIrp, STATUS_UNSUCCESSFUL);
// }
// while (firstBuffer != NULL)
// {
// ULONG length;
// NdisQueryBuffer (firstBuffer, &virtualAddress, &length);
// NdisMoveMappedMemory
// (
// pUserBuffer + offset,
// virtualAddress,
// length
// );
// NdisGetNextBuffer (firstBuffer, &nextBuffer);
// firstBuffer = nextBuffer;
// offset += length;
// }
// }
//
NdisCopyFromPacketToPacket (pPacket, 0, BufferLength, Packet, 0,
&bytesTransfered);
NdisFreePacket (pPacket);
pIrp->IoStatus.Information = bytesTransfered;
CompleteIrp (pIrp, STATUS_SUCCESS);
return 0;
}
NTSTATUS LanWrite
(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
{
PNDIS_PACKET pPacket;
NDIS_STATUS Status;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation (pIrp);
POPEN_INSTANCE pInstance = IrpSp->FileObject->FsContext;
NdisAllocatePacket
(
&Status,
&pPacket,
pInstance->PacketPool
);
if (Status != NDIS_STATUS_SUCCESS)
{
return CompleteIrp (pIrp, STATUS_UNSUCCESSFUL);
}
((PPACKET_RESERVED) (pPacket->ProtocolReserved))->Irp = pIrp;
NdisChainBufferAtFront (pPacket, pIrp->MdlAddress);
pIrp->IoStatus.Information = MmGetMdlByteCount (pIrp->MdlAddress);
MarkPending (IrpSp);
NdisSend
(
&Status, pInstance->AdapterHandle, pPacket
);
if (Status == NDIS_STATUS_PENDING)
return STATUS_PENDING;
UnMarkPending (IrpSp);
LanSendComplete (pInstance->BindContext, pPacket,
(Status == NDIS_STATUS_SUCCESS) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
return Status;
}
VOID LanSendComplete
(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET pPacket,
IN NDIS_STATUS Status
)
{
PIRP Irp = ((PPACKET_RESERVED) (pPacket->ProtocolReserved))->Irp;
NdisReinitializePacket (pPacket);
NdisFreePacket (pPacket);
if (Status == NDIS_STATUS_SUCCESS)
{
CompleteIrp (Irp, STATUS_SUCCESS);
}
else
{
Irp->IoStatus.Information = 0;
CompleteIrp (Irp, STATUS_UNSUCCESSFUL);
}
}
Пока на собственное сообщение не было ответов, его можно удалить.
Удалить