запуск драйвера в XP
От: 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);
}
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.