Network driver

hi everyone ,

i was trying for the last month to write a network driver that intercept
incoming (compressed) data, uncompress it and forward it, but without any
result. Does anyone have a suggestion ? is there a lot of work to do ?

here is a portion of code i wrote :

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObjectNetwork,

IN PUNICODE_STRING RegistryPath )

{

NTSTATUS status = STATUS_SUCCESS;
UINT uindex = 0;
UNICODE_STRING usDriverName, usDosDeviceName, deviceObjectNetworkName;

DbgPrint(“DriverEntry Called \r\n”);

RtlInitUnicodeString(&usDriverName, L"\Device\networkTest");
RtlInitUnicodeString(&usDosDeviceName, L"\DosDevices\networkTest");

status = IoCreateDevice(pDriverObjectNetwork,
sizeof(DEVICE_EXTENSION),
&usDriverName,
FILE_DEVICE_NETWORK,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&pDeviceObjectNetwork
);

if (!NT_SUCCESS(status))
return status;

for(uindex = 0; uindex < IRP_MJ_MAXIMUM_FUNCTION; uindex++)
pDriverObjectNetwork->MajorFunction[uindex] = PassThrough;

pDriverObjectNetwork->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
OnDeviceControl;
pDriverObjectNetwork->DriverUnload =
OnUnload;

pDeviceObjectNetwork->Flags = pDeviceObjectNetwork->Flags
| DO_DIRECT_IO;

pDeviceObjectNetwork->Flags = pDeviceObjectNetwork->Flags
& ~DO_DEVICE_INITIALIZING;

RtlZeroMemory(pDeviceObjectNetwork->DeviceExtension,
sizeof(DEVICE_EXTENSION));

pDeviceExtensionNetwork
=(PDEVICE_EXTENSION)(pDeviceObjectNetwork->DeviceExtension) ;

if (!pDeviceExtensionNetwork){
DbgPrint(“et merde… l’extension”);
return 1;
}

RtlInitUnicodeString(&deviceObjectNetworkName, L"\Device\Tcp");

status = IoAttachDevice(pDeviceObjectNetwork,
&deviceObjectNetworkName,
&pDeviceExtensionNetwork->pNetworkDevice
);

if (!pDeviceExtensionNetwork->pNetworkDevice){
OnUnload(pDriverObjectNetwork);
return 1;
}

IoCreateSymbolicLink(&usDosDeviceName, &usDriverName);

return STATUS_SUCCESS;

}

***********************
NTSTATUS OnDeviceControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIRP
)
{

IoCopyCurrentIrpStackLocationToNext(pIRP);

IoSetCompletionRoutine(pIRP,
OnReadCompletion,
DeviceObject,
TRUE,
TRUE,
TRUE
);

return IoCallDriver(
((PDEVICE_EXTENSION)
pDeviceObjectNetwork->DeviceExtension)->pNetworkDevice, pIRP);

}

************************
NTSTATUS OnReadCompletion(IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIRP, IN PVOID Context
)
{

DbgPrint(“OnReadCompletion called … %d”,
compteur
);

compteur+=pIRP->IoStatus.Information;

if(pIRP->PendingReturned)

IoMarkIrpPending(pIRP);

return pIRP->IoStatus.Status;

}

**************************
void OnUnload (IN PDRIVER_OBJECT pDriverObject){

DbgPrint(“Deleting symbolic link …”);

IoDeleteSymbolicLink(&usDosDeviceName);

DbgPrint(“Detaching device …”);

IoDetachDevice(pDeviceExtensionNetwork->pNetworkDevice);

DbgPrint(“Deleting device …”);

IoDeleteDevice(pDriverObject->DeviceObject);

RtlFreeUnicodeString(&deviceObjectNetworkName);
RtlFreeUnicodeString(&usDriverName);
RtlFreeUnicodeString(&usDosDeviceName);
}

every time i load my driver, i got some output on dbgview’s screen, but
always smaller than the real size of the page (sometimes much smaller), and
when i unload it i get a BSoD.

please help.

thanx

PS: sorry for my poor english.

First of all, it is better to use IoGetDeviceObjectPointer()- IoAttachDeviceToDeviceStack() sequence.
Second, you should clear DO_DEVICE_INITIALIZING flag *AFTER* having attached your device to the stack and not before doing it - apparently, IoAttachDevice() sets this flag behind the scenes. As long as this flag is set, no one can attach to your device, and this is what IoAttachDevice(), apparently, wants - it does not want new devices being attached until the current operation completes sucessfully, does it? Therefore, I believe it sets this flag, and it is your responsibility to clear it (i.e. something that you don’t do).

IIRC, on one occasion I forgot to clear DO_DEVICE_INITIALIZING flag after having attached my device in DriverEntry(), and, as a result, bluescreed in my Unload() routine. In other words, I am not surprized about BSOD at all…

Anton Bassov

ok thanx for the quick response,

here my new code :
.
.status = IoGetDeviceObjectPointer(&deviceObjectNetworkName,
DELETE | SYNCHRONIZE,
&pDeviceExtensionNetwork->fileObject,
&pHeadOfStackDevice
);

if (!NT_SUCCESS(status)){
DbgPrint(“IoGetDeviceObjectPointer a echoue”);
return status;
}

pDeviceExtensionNetwork->pNetworkDevice =IoAttachDeviceToDeviceStack(pDeviceObjectNetwork,
pHeadOfStackDevice
);

if (!pDeviceExtensionNetwork->pNetworkDevice){
DbgPrint(“IoAttachDeviceToDeviceStack a echoue”);
OnUnload(pDriverObjectNetwork);
return 1;
}

IoCreateSymbolicLink(&usDosDeviceName, &usDriverName);

pDeviceObjectNetwork->Flags = pDeviceObjectNetwork->Flags
& ~DO_DEVICE_INITIALIZING;

return STATUS_SUCCESS;
}

but still have the other problems, any idea about them ?

You may not like to hear my advice.

1.) You MUST use WinDbg - NOT dbgview if you have any hope of being
successful in driver development. It is unacceptable for a driver writer to
say “I got a BSOD” when there are tools to provide much more information.

2.) You CANNOT unload a filter driver of this type without causing a
crash.

3.) STOP writing your filter - at least for the moment.

First, take time to decide if your decompression could be done on a
packet-by-packet basis at the NDIS layer instead of at the TDI layer. If it
can be done at NDIS layer, ABANDON your current approach and write a
decompressing NDIS Intermediate filter driver to do the work. Still a lot of
work, but overall much better chance of success.

STOP and STUDY the Transport Data Interface (TDI) very carefully. It is
difficult to read in some cases, but is actually mostly correct.

As part of your study you MUST take time to write a few TDI client
drivers. I know I wrote several as part of my studies. You MUST know what
is passed to the TDI layer before you can attempt to filter it. For you I
would recommend writing a ECHO server using TDI before trying to write a TDI
filter. Make sure that when you write your ECHO server that you explore
using both TDI_RECEIVE and the receive event handlers.

One benefit of writing your own TDI client is that you can use it when (and
if.) you resume work on your TDI filter. You can concurrently debug your TDI
client and your TDI filter, which is helpful in the early stages.

This is a big job. Good luck!

Thomas F. Divine

From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Cherfi Mehdi
Sent: Sunday, July 29, 2007 9:57 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] Network driver

hi everyone ,

i was trying for the last month to write a network driver that intercept
incoming (compressed) data, uncompress it and forward it, but without any
result. Does anyone have a suggestion ? is there a lot of work to do ?

here is a portion of code i wrote :

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObjectNetwork,

IN PUNICODE_STRING RegistryPath )

{

NTSTATUS status = STATUS_SUCCESS;
UINT uindex = 0;
UNICODE_STRING usDriverName, usDosDeviceName, deviceObjectNetworkName;

DbgPrint(“DriverEntry Called \r\n”);

RtlInitUnicodeString(&usDriverName, L"\Device\networkTest");
RtlInitUnicodeString(&usDosDeviceName, L"\DosDevices\networkTest");

status = IoCreateDevice(pDriverObjectNetwork,
sizeof(DEVICE_EXTENSION),
&usDriverName,
FILE_DEVICE_NETWORK,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&pDeviceObjectNetwork
);

if (!NT_SUCCESS(status))
return status;

for(uindex = 0; uindex < IRP_MJ_MAXIMUM_FUNCTION; uindex++)
pDriverObjectNetwork->MajorFunction[uindex] = PassThrough;

pDriverObjectNetwork->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
OnDeviceControl;
pDriverObjectNetwork->DriverUnload =
OnUnload;

pDeviceObjectNetwork->Flags = pDeviceObjectNetwork->Flags
| DO_DIRECT_IO;

pDeviceObjectNetwork->Flags = pDeviceObjectNetwork->Flags
& ~DO_DEVICE_INITIALIZING;

RtlZeroMemory(pDeviceObjectNetwork->DeviceExtension,
sizeof(DEVICE_EXTENSION));

pDeviceExtensionNetwork
=(PDEVICE_EXTENSION)(pDeviceObjectNetwork->DeviceExtension) ;

if (!pDeviceExtensionNetwork){
DbgPrint(“et merde… l’extension”);
return 1;
}

RtlInitUnicodeString(&deviceObjectNetworkName, L"\Device\Tcp");

status = IoAttachDevice(pDeviceObjectNetwork,
&deviceObjectNetworkName,
&pDeviceExtensionNetwork->pNetworkDevice
);

if (!pDeviceExtensionNetwork->pNetworkDevice){
OnUnload(pDriverObjectNetwork);
return 1;
}

IoCreateSymbolicLink(&usDosDeviceName, &usDriverName);

return STATUS_SUCCESS;

}

***********************
NTSTATUS OnDeviceControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIRP
)
{

IoCopyCurrentIrpStackLocationToNext(pIRP);

IoSetCompletionRoutine(pIRP,
OnReadCompletion,
DeviceObject,
TRUE,
TRUE,
TRUE
);

return IoCallDriver(
((PDEVICE_EXTENSION)
pDeviceObjectNetwork->DeviceExtension)->pNetworkDevice, pIRP);

}

************************
NTSTATUS OnReadCompletion(IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIRP, IN PVOID Context
)
{

DbgPrint(“OnReadCompletion called … %d”,
compteur
);

compteur+=pIRP-> IoStatus.Information;

if(pIRP->PendingReturned)

IoMarkIrpPending(pIRP);

return pIRP->IoStatus.Status;

}

**************************
void OnUnload (IN PDRIVER_OBJECT pDriverObject){

DbgPrint(“Deleting symbolic link …”);

IoDeleteSymbolicLink(&usDosDeviceName);

DbgPrint(“Detaching device …”);

IoDetachDevice(pDeviceExtensionNetwork->pNetworkDevice);

DbgPrint(“Deleting device …”);

IoDeleteDevice(pDriverObject->DeviceObject);

RtlFreeUnicodeString(&deviceObjectNetworkName);
RtlFreeUnicodeString(&usDriverName);
RtlFreeUnicodeString(&usDosDeviceName);
}

every time i load my driver, i got some output on dbgview’s screen, but
always smaller than the real size of the page (sometimes much smaller), and
when i unload it i get a BSoD.

please help.

thanx

PS: sorry for my poor english.
— NTDEV is sponsored by OSR For our schedule of WDF, WDM, debugging and
other seminars visit: http://www.osr.com/seminars To unsubscribe, visit the
List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Thomas F. Divine a écrit :

You may not like to hear my advice.

1.) You /MUST/ use WinDbg - /NOT/ dbgview if you have any hope of
being successful in driver development. It is unacceptable for a driver
writer to say “I got a BSOD” when there are tools to provide much more
information.

2.) You /CANNOT/ unload a filter driver of this type without
causing a crash/./

3.) /STOP/ writing your filter – at least for the moment.

First, take time to decide if your decompression could be done on a
packet-by-packet basis at the NDIS layer instead of at the TDI layer. If
it can be done at NDIS layer, /ABANDON/ your current approach and
write a decompressing NDIS Intermediate filter driver to do the work.
Still a lot of work, but overall much better chance of success.

/STOP/ and /STUDY/ the Transport Data Interface (TDI) very
carefully. It is difficult to read in some cases, but is actually mostly
correct.

As part of your study you /MUST/ take time to write a few TDI client
drivers. I know I wrote several as part of my studies. You /MUST/ know
what is passed to the TDI layer before you can attempt to filter it. For
you I would recommend writing a ECHO server using TDI before trying to
write a TDI filter. Make sure that when you write your ECHO server that
you explore using both TDI_RECEIVE and the receive event handlers.

One benefit of writing your own TDI client is that you can use it when
(and if…) you resume work on your TDI filter. You can concurrently debug
your TDI client and your TDI filter, which is helpful in the early stages.

This is a big job. Good luck!

Thomas F. Divine

thanks a lot for the advises, so i will do what you suggest about TDI
client (i must use TDI filter, my decompression can’t be done on a
packet-by-packet basis), i just hope it won’t take a lot of time, cause
i don’t have .

thanks to all of you.

> but still have the other problems, any idea about them ?

What I told you, in my opinion, applies to *ANY* legacy stack - although MSDN claims that, as long as you attach your device in DriverEntry() you don’t have to be bothered about DO_DEVICE_INITIALIZING flag because IO Manager clears it itself, in my experience this is not the case, and your post seems to confirm it.

What I forgot to tell you is that TDI filter (as well as any other legacy filter) is not the kind of driver that can be made stoppable - the only situation when you can temporarily afford it is at the very early stage of driver development…

Anton Bassov

The old NT style drivers that do all the processing in DriverEntry that is
currently done in DriverEntry, AddDevice, & the IRP_MJ_START do not have to
clear the DO_DEVICE_INITIALIZING flag. Normally WDM drivers clear that flag
in AddDevice just before returning to the OS because doing that can cause
other requests to begin arriving. Some of this does not apply to miniport
drivers of various kinds.

As far as I am concerned, “legacy stack” refers to NT4 style drivers. WDM
is a subset of the NT drivers that began with Windows 2000 that had to
support PnP and power. WDF is just a wrapper around the full ‘NT’ type of
driver that began with 2k. Miniports are another thing and the rules don’t
apply to them in the same way.


David J. Craig
Engineer, Sr. Staff Software Systems
Broadcom Corporation

wrote in message news:xxxxx@ntdev…
>> but still have the other problems, any idea about them ?
>
> What I told you, in my opinion, applies to ANY legacy stack - although
> MSDN claims that, as long as you attach your device in DriverEntry() you
> don’t have to be bothered about DO_DEVICE_INITIALIZING flag because IO
> Manager clears it itself, in my experience this is not the case, and your
> post seems to confirm it.
>
> What I forgot to tell you is that TDI filter (as well as any other legacy
> filter) is not the kind of driver that can be made stoppable - the only
> situation when you can temporarily afford it is at the very early stage of
> driver development…
>
> Anton Bassov
>

> The old NT style drivers that do all the processing in DriverEntry that is

currently done in DriverEntry, AddDevice, & the IRP_MJ_START do not have to
clear the DO_DEVICE_INITIALIZING flag.

This is what MSDN says - indeed, according to it, if you attach your device to the stack in DriverEntry() you do not have to clear the DO_DEVICE_INITIALIZING flag. However, in my experience, things may work a bit differently, and the OP’s post seems to confirm it - although it did not solve all his problems, for understandable reasons, clearing the DO_DEVICE_INITIALIZING flag seems to have
solved the one with BSOD in Unload() routine. Actually, I don’t exclude the possibility that the whole thing depends on OS version…

As far as I am concerned, “legacy stack” refers to NT4 style drivers.

There are quite a few of them around - FS and protocol stacks (its IRP-based edge, of course) are the very first examples that come to my mind…

Miniports are another thing and the rules don’t apply to them in the same way.

The same story with protocols…

The situation with protocols is really interesting - on their lower (i.e. NDIS) edge protocols of NDIS version >=4 are PnP-compliant, but on their upper one (i.e. IRP-based ) they are legacy drivers…

Anton Bassov