Need Help with TDI Driver

Hello,

I have about 1 day’s experience with Win2K drivers so bear with me if
my question is overly trivial.

I’m trying to create something that is capable of observing all TCP/IP
traffic entering or leaving the local machine, regardless of physical
layer. I figured the best way to do this would be to write a TDI
driver. My current approach is basically as follows:

  1. Call ZwCreateFile() to get a handle to \device\tcp
  2. Call ObReferenceObjectByHandle() to get the corresponding file
    object
  3. Call IoGetRelatedDeviceObject() to get the device object
  4. Call TdiBuildInternalDeviceIrp() and TdiBuildSetEventHandler() to
    build
    an IRP to register a function that will be called by the transport
    driver
    when it receives something.
  5. Call IoCallDevice() to send the IRP to the lower level.

I’m having trouble here, though, because IoCallDevice() returns
0xC0000010 (invalid device request) when I try to send the IRP. I
have no idea why this is happening; from what I can tell, I’m
adhering to the steps outlined in the DDK for accomplishing this sort
of thing. Does anybody know why this might be happening? [code is
included at the end of this message]

Also, a less specific question – is this a good approach for what I’m
trying to do? I’ve been looking at other driver source code from
various places and am wondering if I should be just using
CreateDevice() and then IoAttachDevice() to attach to the \device\tcp
chain. Assumedly, I would then be catching every request going to
\device\tcp, and I could do what I wanted with the data and then have
a dispatch routine to pass on the IRP when I was finished. Is this
possible, and if so, what are the advantages/disadvantages compared to
the first approach?

Thanks in advance,
-chris

— [start code]

HANDLE tcpip;
PVOID pfileobject;
PVOID pdeviceobject;

NTSTATUS tdidrv_ClientEventReceive (
IN PVOID TdiEventContext,
IN CONNECTION_CONTEXT ConnectionContext,
IN ULONG ReceiveFlags,
IN ULONG BytesIndicated,
IN ULONG BytesAvailable,
OUT ULONG *BytesTaken,
IN PVOID Tsdu,
OUT PIRP *IoRequestPacket
)
{
#if DEBUG
DbgPrint(“tdidrv_ClientEventReceive() got called\n”);
#endif
return STATUS_SUCCESS;
}

NTSTATUS DriverUnload(
IN PDRIVER_OBJECT DriverObject
)
{
#if DEBUG
DbgPrint(“Calling ObDereference() and ZwClose()\n”);
#endif

ObDereferenceObject(pfileobject);
ZwClose(tcpip);

return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
IO_STATUS_BLOCK io_status;
OBJECT_ATTRIBUTES obj_attrib;
NTSTATUS dstatus;

OBJECT_HANDLE_INFORMATION obj_handle_info;
PIRP mypirp;

WCHAR name = L"\device\tcp";
UNICODE_STRING u_name;
RtlInitUnicodeString(&u_name, name);

DriverObject->DriverUnload = DriverUnload;

InitializeObjectAttributes(&obj_attrib,
&u_name,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
dstatus = ZwCreateFile(&tcpip,
GENERIC_READ | GENERIC_WRITE,
&obj_attrib,
&io_status,
0L,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
FILE_DIRECTORY_FILE,
NULL,
0L);
#if DEBUG
DbgPrint(“\n.\n.\nZwCreateFile() return code: %08X\n”, dstatus);
DbgPrint(“Handle to %ws: %08X\n”, name, (unsigned long) tcpip);
#endif
if (dstatus) {
DbgPrint(“ZwCreateFile() failed\n”);
return STATUS_INSUFFICIENT_RESOURCES;
}

dstatus = ObReferenceObjectByHandle(tcpip,
FILE_READ_ACCESS,
NULL,
KernelMode,
&pfileobject,
&obj_handle_info);
#if DEBUG
DbgPrint(“ObReferenceObjectByHandle() return code: %08X\n”, dstatus);
DbgPrint(“Pointer to file object: %08X\n”, pfileobject);
#endif
if (dstatus) {
DbgPrint(“ObReferenceObjectByHandle() failed\n”);
ZwClose(tcpip);
return STATUS_INSUFFICIENT_RESOURCES;
}

pdeviceobject = IoGetRelatedDeviceObject(pfileobject);
if (pdeviceobject == NULL) {
DbgPrint(“IoGetRelatedDeviceObject() failed\n”);
ZwClose(tcpip);
return STATUS_INSUFFICIENT_RESOURCES;
}

#if DEBUG
DbgPrint(“Pointer to related device object: %08X\n”, pdeviceobject);
#endif

mypirp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER,
pdeviceobject,
pfileobject, NULL,
&io_status);
#if DEBUG
DbgPrint(“Pointer to mypirp: %08X\n”, mypirp);
#endif
if (mypirp == NULL) {
DbgPrint(“TdiBuildInternalDeviceControlIrp() failed\n”);
ZwClose(tcpip);
ObDereferenceObject(pfileobject);
return STATUS_INSUFFICIENT_RESOURCES;
}

TdiBuildSetEventHandler(mypirp,
pdeviceobject,
pfileobject,
NULL,
NULL,
TDI_EVENT_RECEIVE,
tdidrv_ClientEventReceive,
NULL);
//
// THIS IoCallDriver() CALL IS FAILING WITH STATUS 0xC0000010
dstatus = IoCallDriver(pdeviceobject,
mypirp);
#if DEBUG
DbgPrint(“IoCallDriver() return code: %08X\n”, dstatus);
#endif
if (dstatus) {
DbgPrint(“IoCallDriver() failed\n”);
ZwClose(tcpip);
ObDereferenceObject(pfileobject);
return STATUS_INSUFFICIENT_RESOURCES;
}

return STATUS_SUCCESS;
}

— [end code]


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

> I’m trying to create something that is capable of observing all TCP/IP

traffic entering or leaving the local machine

This has *so* been done. Just use WinPCap (http://netgroup-serv.polito.it/winpcap/).

– CCP

----- Original Message -----
From: “Chris Eng”
To: “NT Developers Interest List”
Sent: Wednesday, January 23, 2002 8:23 PM
Subject: [ntdev] Need Help with TDI Driver




You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com