Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTDEV

Before Posting...

Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


RE: TIMING

OSR_Community_UserOSR_Community_User Member Posts: 110,217
From my (not great) experience with timing function granularity issues
it seems that calling the Sleep() function with values like 1 or 2 does
NOT have the intuitive result namely to wake up in 1 or 2 ms. This
(please correct me if I err) is because time values are only updated at
the clock tick. So calling right AFTER the tick has the same effect as
Sleep(10). Right? If this is so, why describe Sleep as having a 1 ms
granularity?

Bill Casey

== SCSI Adapters & VirtualSCSI Target Mode Libs ==
Galveston, TX 77554 USA www.virtualscsi.com



-----Original Message-----
From: [email protected]
[mailto:[email protected]]On Behalf Of [email protected]
Sent: Monday, August 07, 2000 3:29 PM
To: NT Developers Interest List
Subject: [ntdev] Re: TDI drivers question



Actually, you would be writing a TDI Client - not a driver. There is
sample code in the DDK.

But what you probably want to do is write an NDIS driver - that would
allow
you to listen to any network traffic to any
NIC that the NDIS driver is bound to.

Here is some code
(example only) that will allow you to get your local IP Address.

The sample code from the DDK is in DDK\SRC\FileSys\Rdr2\Supplied\RxCE.

You can also get sample TDI Client code from www.osr.com

Look in the DDK for TDI Client information.

////////////////////////////////////////////////////////////////////////
///////
////////////////////////////////////////////////////////////////////////
///////
NTSTATUS CDispatchTable::TdiOpenTransport( IN PWSTR pProtocol, IN USHORT
wPort)
{
CTcpAddress::IP_TRANSPORT_ADDRESS* pAddress; //
transport
address
ULONG dEaLength;
//
buffer size
PFILE_FULL_EA_INFORMATION pEaInfo; // pointer
to
ea
NTSTATUS dStatus; // current
status

dEaLength = sizeof ( FILE_FULL_EA_INFORMATION ) +
//
account for ea
sizeof ( TdiTransportAddress ) +
//
account for transport
sizeof ( CTcpAddress::IP_TRANSPORT_ADDRESS ) + 1;
//
account for ip address
pEaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool
NonPagedPool,

dEaLength );
if ( pEaInfo )
//
validate pointer
{
RtlZeroMemory ( pEaInfo, dEaLength );
//
clear eabuffer
pEaInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
//
size

RtlCopyMemory ( pEaInfo->EaName,
//
copy transport name
TdiTransportAddress,
sizeof ( TdiTransportAddress ) );

pEaInfo->EaValueLength = sizeof ( TA_IP_ADDRESS );
//
size of data

pAddress = (CTcpAddress::IP_TRANSPORT_ADDRESS*)(
pEaInfo->EaName +
sizeof (
TdiTransportAddress ));

pAddress->TAAddressCount = 1;
//
number of addresses
pAddress->Address[0].AddressLength = sizeof
( TDI_ADDRESS_IP );
pAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
pAddress->Address[0].ipAddr.sin_port = //
local port
W_LITTLE_TO_BIG_ENDIAN(wPort);

pAddress->Address[0].ipAddr.in_addr = 0L; //
local address
dStatus = TdiOpen (pProtocol, // tdi
device
name
dEaLength, // length
of
ea info
pEaInfo, //
pointer to ea info
&m_hTdiTransport, // return
transport
handle
&m_pTdiTransportFileObject );// return
transport
object

if ( NT_SUCCESS ( dStatus ) ) // check for valid return
{
m_LocalPort = W_LITTLE_TO_BIG_ENDIAN(wPort);
}
else
{
m_LocalPort = 0;
}

ExFreePool ( pEaInfo ); // free buffer
}

return ( dStatus );
}

////////////////////////////////////////////////////////////////////////
///////
////////////////////////////////////////////////////////////////////////
///////

NTSTATUS CDispatchTable::TdiOpen ( IN PWSTR
pProtocol,
IN ULONG
dEaLength,
IN
PFILE_FULL_EA_INFORMATION
pEaInfo,
OUT PHANDLE
phHandle,
OUT PFILE_OBJECT*
ppObject )
{
UNICODE_STRING uName; // local name
OBJECT_ATTRIBUTES ObjectAttrib; // local object attribute
IO_STATUS_BLOCK IoStatusBlock; // local io status return
NTSTATUS dStatus; // current status

RtlInitUnicodeString ( &uName, pProtocol ); // get
device
name

InitializeObjectAttributes( &ObjectAttrib, // return
object attribute
&uName,
//
resource name
OBJ_CASE_INSENSITIVE, //
attributes
NULL,
//
root directory
NULL );
//
security descriptor

dStatus = ZwCreateFile ( phHandle,
//
return file handle
GENERIC_READ | GENERIC_WRITE,
// desired access
&ObjectAttrib,
// local object attribute
&IoStatusBlock,
// local io status
0L,
// initial allocation size
FILE_ATTRIBUTE_NORMAL,
// file attributes
FILE_SHARE_READ |
FILE_SHARE_WRITE, // share access
FILE_OPEN_IF,
// create disposition
0L,
// create options
pEaInfo,
// eabuffer
dEaLength );
// ealength

if ( NT_SUCCESS ( dStatus ) ) // check for valid return
{
dStatus = ObReferenceObjectByHandle ( *phHandle,
// handle to open file

FILE_ALL_ACCESS, // access mode
NULL,
// object type
KernelMode,
// access mode

(void**)ppObject, // pointer to object
NULL );
// handle information


if ( !NT_SUCCESS ( dStatus ) )
{
ZwClose ( *phHandle ); // close handle
m_hLocalIP = 0;
}
else
{
m_hLocalIP = *phHandle;
}
}

return ( dStatus );
}

////////////////////////////////////////////////////////////////////////
///////
////////////////////////////////////////////////////////////////////////
///////

NTSTATUS CDispatchTable::TdiQueryAddress( IN PFILE_OBJECT pObject,
IN PULONG
pdAddress
)
{
ULONG i, j;
// local loop control
TDIEntityID* pEntityBuffer = NULL;
// buffer for ENTITY_LIST_ID
ULONG dEntityCount;
// number of entities
ULONG dEntityType;
// entity type
IPSNMPInfo SnmpInfo;
// ip information
CTcpAddress::IPAddrEntry* pIpAddress = NULL;
// ip address buffer
ULONG dBufferSize =
MAX_FAST_ENTITY_BUFFER ; // buffer length
NTSTATUS dStatus =
STATUS_INVALID_PARAMETER; // local status

*pdAddress = 0L;
for ( j = 0; j < 2; j++ )
{
pEntityBuffer = (TDIEntityID *)ExAllocatePool
NonPagedPool,

dBufferSize );

if ( pEntityBuffer == NULL ) //
validate pointer
{
DbgPrint ( "ERROR: ExAllocatePoolWithTag\n" );
dStatus = STATUS_INSUFFICIENT_RESOURCES;
break;
}
else
{
// ********************************************
// 1-Query device for entity buffer
// ********************************************
dStatus = TdiQueryInformationExEntry ( pObject,
// control object

GENERIC_ENTITY, // entity

TL_INSTANCE, // instance

INFO_CLASS_GENERIC, // class

INFO_TYPE_PROVIDER, // type

ENTITY_LIST_ID, // id

pEntityBuffer, // output buffer

&dBufferSize ); // output buffer size

if ( dStatus == STATUS_BUFFER_TOO_SMALL )
//
check for a buffer error
{
DbgPrint ( "ERROR: Buffer too small\n", dStatus );
ExFreePool ( pEntityBuffer );
// free buffer
pEntityBuffer = NULL;
}
else
{
if ( !NT_SUCCESS ( dStatus ) )
// check return code
DbgPrint ( "ERROR: Unable to get entity\n",
dStatus );
break;
}
}
}

// *********************************
// Scan the entities looking for IP.
// *********************************
if ( NT_SUCCESS ( dStatus ) )
{
dEntityCount = dBufferSize / sizeof ( TDIEntityID ); //
determine number of entities
for ( i = 0; i < dEntityCount; i++ ) //
loop through all of them
{
// ********************************************
// 2-Query device for entity type
// ********************************************
if ( pEntityBuffer[i].tei_entity == CL_NL_ENTITY )
{
dBufferSize = sizeof ( dEntityType );
// store buffer size
if ( NT_SUCCESS ( dStatus ) )
// validate pointer
{
dStatus = TdiQueryInformationExEntry
pObject,
// control object

CL_NL_ENTITY, // entity

pEntityBuffer[i].tei_instance,// instance

INFO_CLASS_GENERIC, // class

INFO_TYPE_PROVIDER, // type

ENTITY_TYPE_ID, // id

&dEntityType, // output buffer

&dBufferSize ); // output buffer size

if ( !NT_SUCCESS ( dStatus ) || ( dEntityType
!=
CL_NL_IP ) ) // check for IP entity type
DbgPrint ( "ERROR: Unable to get entity
type\n", dStatus );
}

// ***************************************
// 3-Query device for snmp info.
// We found an IP entity. Now lookup its
// addresses. Start by querying the number
// of addresses supported by this interface.
// ***************************************

if ( NT_SUCCESS ( dStatus ) )
{
dBufferSize = sizeof ( SnmpInfo ); // store
buffer size

dStatus = TdiQueryInformationExEntry
pObject,
// control object

CL_NL_ENTITY, // entity

pEntityBuffer[i].tei_instance,// instance

INFO_CLASS_PROTOCOL, // class

INFO_TYPE_PROVIDER, // type

IP_MIB_STATS_ID, // id

&SnmpInfo, // output buffer

&dBufferSize ); // output buffer size

if ( !NT_SUCCESS ( dStatus ) || (
SnmpInfo.ipsi_numaddr == 0 ) )
DbgPrint ( "ERROR: Unable to get snmp\n",
dStatus );
}
// ***************************************
// 4-Query device for all ip addresses
// ***************************************
if ( NT_SUCCESS ( dStatus ) )
{
dBufferSize = SnmpInfo.ipsi_numaddr * sizeof (
CTcpAddress::IPAddrEntry );
for ( j = 0; j < 2; j++ )
{
pIpAddress = (CTcpAddress::IPAddrEntry
*)ExAllocatePool ( NonPagedPool,

dBufferSize );
if ( pIpAddress == NULL )
{
DbgPrint ( "ERROR:
ExAllocatePoolWithTag\n" );
dStatus =
STATUS_INSUFFICIENT_RESOURCES;
break;
}
else
{
dStatus = TdiQueryInformationExEntry
(
pObject, // control object

CL_NL_ENTITY, // entity

pEntityBuffer[i].tei_instance, // instance

INFO_CLASS_PROTOCOL, // class

INFO_TYPE_PROVIDER, // type

IP_MIB_ADDRTABLE_ENTRY_ID, // id

pIpAddress, // output buffer

&dBufferSize ); // output buffer size

if ( dStatus ==
STATUS_BUFFER_TOO_SMALL
) // check for a buffer error
{
DbgPrint ( "ERROR: Buffer too
small\n", dStatus );
ExFreePool ( pIpAddress );
// free buffer
pIpAddress = NULL;
// reset pointer
}
else
{
if ( !NT_SUCCESS
( dStatus ) )//
check return code
{
DbgPrint ( "ERROR: Unable
to
get address\n", dStatus );
}
else
{

if ( pdAddress )
{
// store real ip
address
*pdAddress =
pIpAddress->iae_addr;
}
}
break; // break for loop
}
}
}
}
}
}
}

if ( pEntityBuffer ) // validate
pointer
ExFreePool ( pEntityBuffer ); // free
buffer
if ( pIpAddress ) // validate
buffer
ExFreePool ( pIpAddress ); // free
buffer
if ( NT_SUCCESS ( dStatus ) && ( *pdAddress == 0L ) )
dStatus = STATUS_INVALID_PARAMETER;

return ( dStatus ); // return with status
}

////////////////////////////////////////////////////////////////////////
///////
////////////////////////////////////////////////////////////////////////
///////

NTSTATUS CDispatchTable::TdiQueryDeviceControl ( IN
PFILE_OBJECT
pObject,
IN
ULONG dIoControlCode,
IN
PVOID InputBuffer,
IN
ULONG InputBufferSize,
IN OUT
PVOID OutputBuffer,
IN
ULONG OutputBufferSize,
OUT
PULONG pdReturn )
{
PIRP pIrp; //
local i/o request
PIO_STACK_LOCATION pIoStack; //
I/O
Stack Location
PDEVICE_OBJECT pDeviceObject; //
local device object
IO_STATUS_BLOCK IoStatusBlock;
// return status
NTSTATUS dStatus =
STATUS_INVALID_PARAMETER;
// default return status

if ( pObject )
{
pDeviceObject = IoGetRelatedDeviceObject ( pObject );
//
get device object

KEVENT kEvent; //
signaling event
KeInitializeEvent ( &kEvent, NotificationEvent, FALSE ); //
reset notification event
pIrp = IoBuildDeviceIoControlRequest ( dIoControlCode,

pDeviceObject,

InputBuffer,

InputBufferSize,

OutputBuffer,

OutputBufferSize,
FALSE,
&kEvent,
// pointer to event

&IoStatusBlock
); // pointer to return
buffer
if ( pIrp == NULL )
{
DbgPrint ( "ERROR: IoBuildDeviceIoControlRequest\n" );
dStatus = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
pIoStack = IoGetNextIrpStackLocation ( pIrp );
// get the iostack
pIoStack->DeviceObject = pDeviceObject;
// store current device object
pIoStack->FileObject = pObject;
// store file object in the stack

dStatus = IoCallDriver ( pDeviceObject, pIrp );
// call next driver
if ( dStatus == STATUS_PENDING )
// make all request synchronous
{
(void)KeWaitForSingleObject ( (PVOID)&kEvent,
// signaling object
Executive,
// wait reason
KernelMode,
// wait mode
TRUE,
// alertable
NULL );
// timeout
}

if ( pdReturn )
// requested by user?
*pdReturn = IoStatusBlock.Information;
// return information size
}
}

return ( dStatus );
//
return with status
}





[email protected] on 08/07/2000 05:25:07 AM

Please respond to "NT Developers Interest List" <[email protected]>

To: "NT Developers Interest List" <[email protected]>
cc:
Subject: [ntdev] TDI drivers question


Hello everybody!

I have a problem, and I hope someone might be able to help.... ;-)

I need a driver that "listens" to the network.
Well, it's NOT a snoop or something like this - I want it
to listen ONLY to IP packets that are designated for the
machine.

In addition, I need it to be able to work on any layer below 3
(i.e.: it should work with modem, ISDN, Ethernet, token ring etc.)

For this reason, I thought to "bind" my driver on top of the TCP/IP
stack,
as a TDI driver. I thought that doing so will make me talk to the TCP/IP
stack
only, using the common API, and I won't need to bother about low-level
protocols.

My questions:
1. Is it possible?
2. Will I see all the IP frames aimed to me? (Note: I want these packets
to arrive BOTH to my TDI driver AND to the application they were
designated to
3. If it's impossible - what's the best way to do so?
4. Does anybody have a sample code?

thanks in advance,

- Barak Mandelovich

------------------------------------------------------------------------
Barak Mandelovich [email protected]
Mercury Interactive ltd.
------------------------------------------------------------------------


---
You are currently subscribed to ntdev as: [email protected]
To unsubscribe send a blank email to $subst('Email.Unsub')





---
You are currently subscribed to ntdev as: [email protected]
To unsubscribe send a blank email to $subst('Email.Unsub')
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. Sign in or register to get started.

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Kernel Debugging 13-17 May 2024 Live, Online
Developing Minifilters 1-5 Apr 2024 Live, Online
Internals & Software Drivers 11-15 Mar 2024 Live, Online
Writing WDF Drivers 20-24 May 2024 Live, Online