Hi,

This is my first driver project. I need to write an upper filter
driver for a serial port which is dynamically loaded from a test
application when required. The driver will be loaded by means of the
Service Control Manager and the driver will connect to the serial port
by means of a special "start" IOCTL call from the test application
using the DeviceIoControl() function, this will pass the name of the
serial port device i.e. \??\COM4". The driver will attach to the named
device leaving it in a state where it can still be opened by a 3rd
party application.

When loaded the driver will monitor incoming and outgoing data on the
port and pass it back to the test application.

I have used two of Walt Oney's sample projects as a starting point for
my code.

My driver loads and unloads OK but when I attempt to open the serial
port from a 3rd party application (Hyperterminal in this case) I get a
bugcheck as described below.

I have included here the "bones" of the DriverEntry, AddDevice and
DispatchAny functions.

The bugcheck occurs at point XXX at the bottom of the DispatchControl
function. I guess I have "broken" the IRP in some way but I don't know
how.

I can't see what the problem is but I am hoping that someone on this
group will be able to see what I can't.

Any help will be gratefully received.

Sorry for such a long post.

Many thanks

O.C.

**** DriverEntry Funtion

extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN
PUNICODE_STRING RegistryPath)
{
// Save the name of the service key

servkey.Buffer = (PWSTR) ExAllocatePool(PagedPool,
RegistryPath->Length + sizeof(WCHAR));
if(!servkey.Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
servkey.MaximumLength = RegistryPath->Length + sizeof(WCHAR);
RtlCopyUnicodeString(&servkey, RegistryPath);
servkey.Buffer[RegistryPath->Length / 2] = 0;

// Initialize function pointers

DriverObject->DriverUnload = DriverUnload;
for (int i = 0; i < arraysize(DriverObject->MajorFunction); ++i)
DriverObject->MajorFunction[i] = DispatchControl;

DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;

// Create a device object to allow an associated application to open
a handle
// in order to send us IOCTL requests

status = AddDevice(DriverObject);

if(!NT_SUCCESS(status))
DriverUnload(DriverObject);

return status;
}

**** AddDevice Function

NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject)
{
PAGED_CODE();
KdPrint((DRIVERNAME " AddDevice(%8.8lX) - Start\n", DriverObject));

NTSTATUS status;

// Create a function device object to represent the hardware we're
managing.

PDEVICE_OBJECT fdo;

UNICODE_STRING devname;

RtlInitUnicodeString(&devname, L"\\DosDevices\\NetMonSerW2kD");
status = IoCreateDevice(DriverObject,
sizeof(DEVICE_EXTENSION),
&devname,
FILE_DEVICE_SERIAL_PORT,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&fdo);
if (!NT_SUCCESS(status))
{
KdPrint((DRIVERNAME " - IoCreateDevice failed - %X\n", status));
return status;
}
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;


// From this point forward, any error will have side effects that
need to
// be cleaned up.

do
{
pdx->DeviceObject = fdo;
pdx->DriverObject = DriverObject;
InitializeListHead(&pdx->registered);
InitializeListHead(&pdx->events);
KeInitializeSpinLock(&pdx->eventlock);

// Make a copy of the device name

pdx->devname.Buffer = (PWCHAR) ExAllocatePool(NonPagedPool,
devname.MaximumLength);
if (!pdx->devname.Buffer)
{ // can't allocate buffer
status = STATUS_INSUFFICIENT_RESOURCES;
KdPrint((DRIVERNAME " - Unable to allocate %d bytes for copy of
name\n", devname.MaximumLength));
break;;
} // can't allocate buffer
pdx->devname.MaximumLength = devname.MaximumLength;
RtlCopyUnicodeString(&pdx->devname, &devname);


// Not sure about this bit.
KeInitializeEvent(&pdx->RemoveLock.evRemove, NotificationEvent,
FALSE);
pdx->RemoveLock.usage = 1;
pdx->RemoveLock.removing = FALSE;

}
while (FALSE);

if(!NT_SUCCESS(status))
{
if (pdx->devname.Buffer)
RtlFreeUnicodeString(&pdx->devname);
IoDeleteDevice(fdo);
}

return status;
}

**** DispatchControl Function

NTSTATUS DispatchControl(PDEVICE_OBJECT fdo, PIRP Irp)
{
PAGED_CODE();

PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

NTSTATUS status = STATUS_SUCCESS;
ULONG info = 0;

PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;
ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;

KdPrint(("\n"DRIVERNAME " DispatchControl() - Irp=%08X IOCTL =
%08X\n",Irp,code));


switch(code)
{
case IOCTL_NETMON_STARTMON:
{
// Copy passed-in data to a unicode string.
// (This will be something like "\??\COM4").

UNICODE_STRING PortName;
WCHAR wPortName[32];

swprintf(wPortName,(WCHAR*)Irp->AssociatedIrp.SystemBuffer,cbin);
RtlInitUnicodeString(&PortName,wPortName);

PFILE_OBJECT FileObject = NULL; // Will be filled in with
pointer to a file object.
PDEVICE_OBJECT DeviceObject = NULL; // Will be filled in with
pointer to a device object.
status=IoGetDeviceObjectPointer(&PortName,
FILE_READ_DATA,
&FileObject,
&DeviceObject);
if(status!=STATUS_SUCCESS)
{
KdPrint((DRIVERNAME " DispatchControl() - Error=%08X\n",status));
break;
}

// "\??\COM4"
if(!FileObject)
break;

if(!DeviceObject)
break;

pdx->Pdo = DeviceObject; // The current device.
// Now attach our device to the device stack.
// Attach our object (which we created with IoCreateDevice() in the
// AddDevice() function and which has been passed to us as the "fdo"
// parameter) to the object we just obtained a pointer to.
// Save a pointer to the device beneath us so we can pass stuff on
to it.

// Attach OUR device object (fdo) to the curent device (ie for
COM4).
pdx->LowerDeviceObject =
IoAttachDeviceToDeviceStack(fdo,DeviceObject);

// Stuff from page 781 of Walt's book...
fdo->Flags |= pdx->LowerDeviceObject->Flags & (DO_DIRECT_IO |
DO_BUFFERED_IO | DO_POWER_PAGABLE);

if(!pdx->LowerDeviceObject)
{
KdPrint((DRIVERNAME " DispatchControl() - Failed to attach\n"));
ObDereferenceObject(FileObject);
break;
}


ObDereferenceObject(FileObject); // Close port again.
status = STATUS_SUCCESS;
info = 0;
KdPrint((DRIVERNAME " DispatchControl() - IOCTL_NETMON_STARTMON
(End)\n"));
break;

}


/***********/
/* Default */
/***********/

default:
KdPrint((DRIVERNAME " DispatchControl() - Default Start\n"));

static char* irpname[] =
{
"IRP_MJ_CREATE",
"IRP_MJ_CREATE_NAMED_PIPE",
"IRP_MJ_CLOSE",
"IRP_MJ_READ",
"IRP_MJ_WRITE",
"IRP_MJ_QUERY_INFORMATION",
"IRP_MJ_SET_INFORMATION",
"IRP_MJ_QUERY_EA",
"IRP_MJ_SET_EA",
"IRP_MJ_FLUSH_BUFFERS",
"IRP_MJ_QUERY_VOLUME_INFORMATION",
"IRP_MJ_SET_VOLUME_INFORMATION",
"IRP_MJ_DIRECTORY_CONTROL",
"IRP_MJ_FILE_SYSTEM_CONTROL",
"IRP_MJ_DEVICE_CONTROL",
"IRP_MJ_INTERNAL_DEVICE_CONTROL",
"IRP_MJ_SHUTDOWN",
"IRP_MJ_LOCK_CONTROL",
"IRP_MJ_CLEANUP",
"IRP_MJ_CREATE_MAILSLOT",
"IRP_MJ_QUERY_SECURITY",
"IRP_MJ_SET_SECURITY",
"IRP_MJ_POWER",
"IRP_MJ_SYSTEM_CONTROL",
"IRP_MJ_DEVICE_CHANGE",
"IRP_MJ_QUERY_QUOTA",
"IRP_MJ_SET_QUOTA",
"IRP_MJ_PNP",
};


UCHAR type = stack->MajorFunction;

if (type >= arraysize(irpname))
KdPrint((DRIVERNAME " Unknown IRP, major type %X\n", type));
else
KdPrint((DRIVERNAME " %s\n", irpname[type]));

// Pass request down without additional processing

NTSTATUS status;

KdPrint((DRIVERNAME " DispatchControl() Def - Calling
IoAcquireRemoveLock(%08X,%08X)\n",pdx->RemoveLock,Irp));
status = IoAcquireRemoveLock(&pdx->RemoveLock,Irp);
KdPrint((DRIVERNAME " DispatchControl() Def - IoAcquireRemoveLock()
acquired %08X and returns %08X\n",pdx->RemoveLock,status));
if (!NT_SUCCESS(status))
return CompleteRequest(Irp, status, 0);


// If there is no lower device object supplied.
if(pdx->LowerDeviceObject==NULL)
{
KdPrint((DRIVERNAME " DispatchControl() Def - No LDO so exit
now\n"));
status=STATUS_SUCCESS;
break;
}

IoSkipCurrentIrpStackLocation(Irp);

KdPrint((DRIVERNAME " DispatchControl() Def - Calling
IoCallDriver(%08X,%08X)\n",pdx->LowerDeviceObject,Irp));
status = IoCallDriver(pdx->LowerDeviceObject,Irp);
KdPrint((DRIVERNAME " DispatchControl() Def - IoCallDriver() returns
%08X\n",status));

if(Irp)
{
IoReleaseRemoveLock(&pdx->RemoveLock,Irp);
}

KdPrint((DRIVERNAME " DispatchControl() Def - End\n"));

break;
}

XXX Bugcheck DRIVER_PAGE_FAULT_IN_FREED_MEMORY_POOL when next
instruction is executed.
The Irp pointer is still the same so I guess the memory it points to
has been released.

Irp->IoStatus.Status = status;
Irp->IoStatus.Information = info;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
} // DispatchControl

Re: Serial Upper Filter Driver Help Required by Mr

Mr
Mon Sep 20 06:17:15 CDT 2004

"Old Codger" wrote...

> Hi,
>
> This is my first driver project. I need to write an upper filter
> driver for a serial port which is dynamically loaded from a test
> application when required. The driver will be loaded by means of the
> Service Control Manager and the driver will connect to the serial port
> by means of a special "start" IOCTL call from the test application
> using the DeviceIoControl() function, this will pass the name of the
> serial port device i.e. \??\COM4". The driver will attach to the named
> device leaving it in a state where it can still be opened by a 3rd
> party application.

You should not expect anything not supported in the standard serial.sys to
work on your filter.
Ie custom DeviceIoControl calls will be lost before they reach your filter.

I solved this by creating a "control" driver in the same workspace as my
serial filter, and controlling the serial filter driver through this
seperate driver.

HTH



Re: Serial Upper Filter Driver Help Required by Maxim

Maxim
Mon Sep 20 07:47:50 CDT 2004

You cannot load/unload WDM filters without stopping/restarting the devnode.

--
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
maxim@storagecraft.com
http://www.storagecraft.com

"Old Codger" <OldCodger101@hotmail.com> wrote in message
news:c339d4a6.0409200126.3df1cca1@posting.google.com...
> Hi,
>
> This is my first driver project. I need to write an upper filter
> driver for a serial port which is dynamically loaded from a test
> application when required. The driver will be loaded by means of the
> Service Control Manager and the driver will connect to the serial port
> by means of a special "start" IOCTL call from the test application
> using the DeviceIoControl() function, this will pass the name of the
> serial port device i.e. \??\COM4". The driver will attach to the named
> device leaving it in a state where it can still be opened by a 3rd
> party application.
>
> When loaded the driver will monitor incoming and outgoing data on the
> port and pass it back to the test application.
>
> I have used two of Walt Oney's sample projects as a starting point for
> my code.
>
> My driver loads and unloads OK but when I attempt to open the serial
> port from a 3rd party application (Hyperterminal in this case) I get a
> bugcheck as described below.
>
> I have included here the "bones" of the DriverEntry, AddDevice and
> DispatchAny functions.
>
> The bugcheck occurs at point XXX at the bottom of the DispatchControl
> function. I guess I have "broken" the IRP in some way but I don't know
> how.
>
> I can't see what the problem is but I am hoping that someone on this
> group will be able to see what I can't.
>
> Any help will be gratefully received.
>
> Sorry for such a long post.
>
> Many thanks
>
> O.C.
>
> **** DriverEntry Funtion
>
> extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN
> PUNICODE_STRING RegistryPath)
> {
> // Save the name of the service key
>
> servkey.Buffer = (PWSTR) ExAllocatePool(PagedPool,
> RegistryPath->Length + sizeof(WCHAR));
> if(!servkey.Buffer)
> return STATUS_INSUFFICIENT_RESOURCES;
> servkey.MaximumLength = RegistryPath->Length + sizeof(WCHAR);
> RtlCopyUnicodeString(&servkey, RegistryPath);
> servkey.Buffer[RegistryPath->Length / 2] = 0;
>
> // Initialize function pointers
>
> DriverObject->DriverUnload = DriverUnload;
> for (int i = 0; i < arraysize(DriverObject->MajorFunction); ++i)
> DriverObject->MajorFunction[i] = DispatchControl;
>
> DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
> DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
>
> // Create a device object to allow an associated application to open
> a handle
> // in order to send us IOCTL requests
>
> status = AddDevice(DriverObject);
>
> if(!NT_SUCCESS(status))
> DriverUnload(DriverObject);
>
> return status;
> }
>
> **** AddDevice Function
>
> NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject)
> {
> PAGED_CODE();
> KdPrint((DRIVERNAME " AddDevice(%8.8lX) - Start\n", DriverObject));
>
> NTSTATUS status;
>
> // Create a function device object to represent the hardware we're
> managing.
>
> PDEVICE_OBJECT fdo;
>
> UNICODE_STRING devname;
>
> RtlInitUnicodeString(&devname, L"\\DosDevices\\NetMonSerW2kD");
> status = IoCreateDevice(DriverObject,
> sizeof(DEVICE_EXTENSION),
> &devname,
> FILE_DEVICE_SERIAL_PORT,
> FILE_DEVICE_SECURE_OPEN,
> FALSE,
> &fdo);
> if (!NT_SUCCESS(status))
> {
> KdPrint((DRIVERNAME " - IoCreateDevice failed - %X\n", status));
> return status;
> }
> PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
>
>
> // From this point forward, any error will have side effects that
> need to
> // be cleaned up.
>
> do
> {
> pdx->DeviceObject = fdo;
> pdx->DriverObject = DriverObject;
> InitializeListHead(&pdx->registered);
> InitializeListHead(&pdx->events);
> KeInitializeSpinLock(&pdx->eventlock);
>
> // Make a copy of the device name
>
> pdx->devname.Buffer = (PWCHAR) ExAllocatePool(NonPagedPool,
> devname.MaximumLength);
> if (!pdx->devname.Buffer)
> { // can't allocate buffer
> status = STATUS_INSUFFICIENT_RESOURCES;
> KdPrint((DRIVERNAME " - Unable to allocate %d bytes for copy of
> name\n", devname.MaximumLength));
> break;;
> } // can't allocate buffer
> pdx->devname.MaximumLength = devname.MaximumLength;
> RtlCopyUnicodeString(&pdx->devname, &devname);
>
>
> // Not sure about this bit.
> KeInitializeEvent(&pdx->RemoveLock.evRemove, NotificationEvent,
> FALSE);
> pdx->RemoveLock.usage = 1;
> pdx->RemoveLock.removing = FALSE;
>
> }
> while (FALSE);
>
> if(!NT_SUCCESS(status))
> {
> if (pdx->devname.Buffer)
> RtlFreeUnicodeString(&pdx->devname);
> IoDeleteDevice(fdo);
> }
>
> return status;
> }
>
> **** DispatchControl Function
>
> NTSTATUS DispatchControl(PDEVICE_OBJECT fdo, PIRP Irp)
> {
> PAGED_CODE();
>
> PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
>
> NTSTATUS status = STATUS_SUCCESS;
> ULONG info = 0;
>
> PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
> ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;
> ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;
> ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
>
> KdPrint(("\n"DRIVERNAME " DispatchControl() - Irp=%08X IOCTL =
> %08X\n",Irp,code));
>
>
> switch(code)
> {
> case IOCTL_NETMON_STARTMON:
> {
> // Copy passed-in data to a unicode string.
> // (This will be something like "\??\COM4").
>
> UNICODE_STRING PortName;
> WCHAR wPortName[32];
>
> swprintf(wPortName,(WCHAR*)Irp->AssociatedIrp.SystemBuffer,cbin);
> RtlInitUnicodeString(&PortName,wPortName);
>
> PFILE_OBJECT FileObject = NULL; // Will be filled in with
> pointer to a file object.
> PDEVICE_OBJECT DeviceObject = NULL; // Will be filled in with
> pointer to a device object.
> status=IoGetDeviceObjectPointer(&PortName,
> FILE_READ_DATA,
> &FileObject,
> &DeviceObject);
> if(status!=STATUS_SUCCESS)
> {
> KdPrint((DRIVERNAME " DispatchControl() - Error=%08X\n",status));
> break;
> }
>
> // "\??\COM4"
> if(!FileObject)
> break;
>
> if(!DeviceObject)
> break;
>
> pdx->Pdo = DeviceObject; // The current device.
> // Now attach our device to the device stack.
> // Attach our object (which we created with IoCreateDevice() in the
> // AddDevice() function and which has been passed to us as the "fdo"
> // parameter) to the object we just obtained a pointer to.
> // Save a pointer to the device beneath us so we can pass stuff on
> to it.
>
> // Attach OUR device object (fdo) to the curent device (ie for
> COM4).
> pdx->LowerDeviceObject =
> IoAttachDeviceToDeviceStack(fdo,DeviceObject);
>
> // Stuff from page 781 of Walt's book...
> fdo->Flags |= pdx->LowerDeviceObject->Flags & (DO_DIRECT_IO |
> DO_BUFFERED_IO | DO_POWER_PAGABLE);
>
> if(!pdx->LowerDeviceObject)
> {
> KdPrint((DRIVERNAME " DispatchControl() - Failed to attach\n"));
> ObDereferenceObject(FileObject);
> break;
> }
>
>
> ObDereferenceObject(FileObject); // Close port again.
> status = STATUS_SUCCESS;
> info = 0;
> KdPrint((DRIVERNAME " DispatchControl() - IOCTL_NETMON_STARTMON
> (End)\n"));
> break;
>
> }
>
>
> /***********/
> /* Default */
> /***********/
>
> default:
> KdPrint((DRIVERNAME " DispatchControl() - Default Start\n"));
>
> static char* irpname[] =
> {
> "IRP_MJ_CREATE",
> "IRP_MJ_CREATE_NAMED_PIPE",
> "IRP_MJ_CLOSE",
> "IRP_MJ_READ",
> "IRP_MJ_WRITE",
> "IRP_MJ_QUERY_INFORMATION",
> "IRP_MJ_SET_INFORMATION",
> "IRP_MJ_QUERY_EA",
> "IRP_MJ_SET_EA",
> "IRP_MJ_FLUSH_BUFFERS",
> "IRP_MJ_QUERY_VOLUME_INFORMATION",
> "IRP_MJ_SET_VOLUME_INFORMATION",
> "IRP_MJ_DIRECTORY_CONTROL",
> "IRP_MJ_FILE_SYSTEM_CONTROL",
> "IRP_MJ_DEVICE_CONTROL",
> "IRP_MJ_INTERNAL_DEVICE_CONTROL",
> "IRP_MJ_SHUTDOWN",
> "IRP_MJ_LOCK_CONTROL",
> "IRP_MJ_CLEANUP",
> "IRP_MJ_CREATE_MAILSLOT",
> "IRP_MJ_QUERY_SECURITY",
> "IRP_MJ_SET_SECURITY",
> "IRP_MJ_POWER",
> "IRP_MJ_SYSTEM_CONTROL",
> "IRP_MJ_DEVICE_CHANGE",
> "IRP_MJ_QUERY_QUOTA",
> "IRP_MJ_SET_QUOTA",
> "IRP_MJ_PNP",
> };
>
>
> UCHAR type = stack->MajorFunction;
>
> if (type >= arraysize(irpname))
> KdPrint((DRIVERNAME " Unknown IRP, major type %X\n", type));
> else
> KdPrint((DRIVERNAME " %s\n", irpname[type]));
>
> // Pass request down without additional processing
>
> NTSTATUS status;
>
> KdPrint((DRIVERNAME " DispatchControl() Def - Calling
> IoAcquireRemoveLock(%08X,%08X)\n",pdx->RemoveLock,Irp));
> status = IoAcquireRemoveLock(&pdx->RemoveLock,Irp);
> KdPrint((DRIVERNAME " DispatchControl() Def - IoAcquireRemoveLock()
> acquired %08X and returns %08X\n",pdx->RemoveLock,status));
> if (!NT_SUCCESS(status))
> return CompleteRequest(Irp, status, 0);
>
>
> // If there is no lower device object supplied.
> if(pdx->LowerDeviceObject==NULL)
> {
> KdPrint((DRIVERNAME " DispatchControl() Def - No LDO so exit
> now\n"));
> status=STATUS_SUCCESS;
> break;
> }
>
> IoSkipCurrentIrpStackLocation(Irp);
>
> KdPrint((DRIVERNAME " DispatchControl() Def - Calling
> IoCallDriver(%08X,%08X)\n",pdx->LowerDeviceObject,Irp));
> status = IoCallDriver(pdx->LowerDeviceObject,Irp);
> KdPrint((DRIVERNAME " DispatchControl() Def - IoCallDriver() returns
> %08X\n",status));
>
> if(Irp)
> {
> IoReleaseRemoveLock(&pdx->RemoveLock,Irp);
> }
>
> KdPrint((DRIVERNAME " DispatchControl() Def - End\n"));
>
> break;
> }
>
> XXX Bugcheck DRIVER_PAGE_FAULT_IN_FREED_MEMORY_POOL when next
> instruction is executed.
> The Irp pointer is still the same so I guess the memory it points to
> has been released.
>
> Irp->IoStatus.Status = status;
> Irp->IoStatus.Information = info;
> IoCompleteRequest(Irp, IO_NO_INCREMENT);
> return status;
> } // DispatchControl



Re: Serial Upper Filter Driver Help Required by OldCodger101

OldCodger101
Tue Sep 21 08:40:53 CDT 2004

"Mr. B" <ask@me> wrote in message news:<ufVAjNwnEHA.4056@TK2MSFTNGP09.phx.gbl>...
> "Old Codger" wrote...
>
> > Hi,
> >
> > This is my first driver project. I need to write an upper filter
> > driver for a serial port which is dynamically loaded from a test
> > application when required. The driver will be loaded by means of the
> > Service Control Manager and the driver will connect to the serial port
> > by means of a special "start" IOCTL call from the test application
> > using the DeviceIoControl() function, this will pass the name of the
> > serial port device i.e. \??\COM4". The driver will attach to the named
> > device leaving it in a state where it can still be opened by a 3rd
> > party application.
>
> You should not expect anything not supported in the standard serial.sys to
> work on your filter.
> Ie custom DeviceIoControl calls will be lost before they reach your filter.
>
> I solved this by creating a "control" driver in the same workspace as my
> serial filter, and controlling the serial filter driver through this
> seperate driver.
>
> HTH

But my driver sits on top of the system device and as such is in a
position to intrcept my special IOCTLS and pass the rest on down. This
bit DOES work!

Anyway - I found THIS problem. I was accessing the Irp for ones I had
passed down and calling IoCompleteRequest instead of just returning
whatever IoCallDrive returned to me.

Re: Serial Upper Filter Driver Help Required by OldCodger101

OldCodger101
Tue Sep 21 08:42:55 CDT 2004

"Maxim S. Shatskih" <maxim@storagecraft.com> wrote in message news:<OEtQH$wnEHA.608@TK2MSFTNGP09.phx.gbl>...
> You cannot load/unload WDM filters without stopping/restarting the devnode.
>
> --
> Maxim Shatskih, Windows DDK MVP
> StorageCraft Corporation
> maxim@storagecraft.com
> http://www.storagecraft.com

Can you explain this further please? I had thought that my driver
could be loaded and attached to the stack and then detached and
unloaded again as long as nothing else has attached on top of it.

Thanks

O.C.

Re: Serial Upper Filter Driver Help Required by Maxim

Maxim
Tue Sep 21 19:04:31 CDT 2004

> Can you explain this further please? I had thought that my driver
> could be loaded and attached to the stack and then detached and
> unloaded again as long as nothing else has attached on top of it.

No. You need to shutdown the stack to detach the driver.

--
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
maxim@storagecraft.com
http://www.storagecraft.com



Re: Serial Upper Filter Driver Help Required by OldCodger101

OldCodger101
Mon Sep 27 05:43:14 CDT 2004

"Maxim S. Shatskih" <maxim@storagecraft.com> wrote in message news:<eYLI2dDoEHA.3488@TK2MSFTNGP12.phx.gbl>...
> > Can you explain this further please? I had thought that my driver
> > could be loaded and attached to the stack and then detached and
> > unloaded again as long as nothing else has attached on top of it.
>
> No. You need to shutdown the stack to detach the driver.

What does IoDetachDevice do then?
Does this not return the stack to the same state it was in before I
attached my device?

Re: Serial Upper Filter Driver Help Required by Maxim

Maxim
Mon Sep 27 08:38:27 CDT 2004

> > No. You need to shutdown the stack to detach the driver.
>
> What does IoDetachDevice do then?

Part of disassembling the stack. WDM drivers must call it in MN_REMOVE_DEVICE
path only.

> Does this not return the stack to the same state it was in before I
> attached my device?

Yes. And for PnP stacks, this occurs only of devnode disabling or surprise
removal.

--
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
maxim@storagecraft.com
http://www.storagecraft.com



Re: Serial Upper Filter Driver Help Required by OldCodger101

OldCodger101
Tue Sep 28 03:05:35 CDT 2004

"Maxim S. Shatskih" <maxim@storagecraft.com> wrote in message news:<#2#G0bJpEHA.3668@TK2MSFTNGP15.phx.gbl>...
> > > No. You need to shutdown the stack to detach the driver.
> >
> > What does IoDetachDevice do then?
>
> Part of disassembling the stack. WDM drivers must call it in MN_REMOVE_DEVICE
> path only.
>
> > Does this not return the stack to the same state it was in before I
> > attached my device?
>
> Yes. And for PnP stacks, this occurs only of devnode disabling or surprise
> removal.

Hi Maxim,

MUST call it in MN_REMOVE_DEVICE - why?

This driver is dynamically loaded by it's associated application by
means of the Service Control Manager then "started" (attached to the
correct COM port) and "stopped" (detached) by means of special IOCTLS
sent via the DeviceIoControl function. The device will never be
"removed" so why can't I detach the driver dynamically myself? There
are commercial products that I am sure use this same method and make
the serial port available for other applications afterwards.

BTW This part is not fully working yet, once I have attached my driver
and dereferenced the file object (to free the serial port) I can
successfully open the port from another applciation (Hyperterminal),
but when I detach the driver the port is no longer available, I have
not found the reason for this yet, maybe that is related to this same
point.

Thanks

O.C.

P.S. Any ideas about my other question "Same IRP appearing more than
once" - I'm behind schedule with this one and urgently need some
answers! :-)

Re: Serial Upper Filter Driver Help Required by Maxim

Maxim
Tue Sep 28 20:54:45 CDT 2004

> MUST call it in MN_REMOVE_DEVICE - why?
>
> This driver is dynamically loaded by it's associated application by
> means of the Service Control Manager then "started" (attached to the
> correct COM port)

Do you mean that you load the driver by SCM, and attach it to PnP stacks? This
is really a way of having problems.

Either is your driver a WDM PnP driver, which is built with DRIVERTYPE=WDM
(this sets the header bit in a SYS binary, which later influences some power
management code) and has a AddDevice routine. Such a driver must not be loaded
by SCM, and, more so, cannot be loaded that way. It must be properly registered
for the proper devnodes - if we are speaking about serial port filter, then add
UpperFilters value to Serial class GUID.

This gives you a lot, for instance, auto-loading your driver for all serial
ports appeared on the machine, including USB ones, Bluetooth ones and so on.

Or - your driver has nothing to do with PnP, has no AddDevice and is loaded by
SCM. Then forget about attaching to PnP stacks. You can only use them as a
client, not intruding inside them as a filter.

>and "stopped" (detached) by means of special IOCTLS
> sent via the DeviceIoControl function.

A way of having hard to debug crashes. For instance, it is nearly impossible to
synchronize this "detach IOCTL" with other IRPs. And, more so - what if there
is one more filter above you? A crash for sure. 100%. So, such code will
inevitably have interop issues with other software.

>The device will never be
> "removed" so why can't I detach the driver dynamically myself?

Because you don't know whether there are more filters above, and if it is so -
then a crash.

>There are commercial products that I am sure use this same method

So what? There are lots of misdesigned badly written software in the world.

> successfully open the port from another applciation (Hyperterminal),
> but when I detach the driver the port is no longer available, I have
> not found the reason for this yet

This is because you're moving in a wrong direction.

Write a WDM PnP filter driver - it's very easy (by far easier then a function
driver), use KBDFILTR as a sample and throw away all code related to keyboard
and i8042 hooks. There are possibly even the pure WDM PnP filter samples in the
DDK - not related to keyboard.

The way to do is:
- design the structure of your device extension
- write a function to fill it properly (similar to C++ constructor) and to
release all resources referenced by it (similar to C++ destructor).
- then write the skeleton of code, which is a DriverEntry routine, which
registers the stupid passthru for all IRP_MJ codes except PnP and Power, and
also the AddDevice routine.
- in AddDevice, call IoCreateDevice, then your "constructor" named above, then
attach to the stack below.
- in DispatchPnP/MN_START_DEVICE, pass the IRP down and wait for it. Then do
all init work which requires sending the IRPs down (if you have such init
work). Do not do such init in AddDevice - can be too early.
- in DispatchPnP/MN_REMOVE_DEVICE, detach from the stack, call your
"destructor" and then IoDeleteDevice.
- pass other PnP IRPs down via the stupid passthru.
- for Power IRPs, the stupid passthru with PoCallDriver instead of IoCallDriver
and with PoStartNextPowerIrp in a proper place (read the doc on IRP stack
location issues with PoStartNextPowerIrp) - is OK as a minimal implementation.

Then replace the IOCTL handler to your own routine and add your IOCTL codes.

Register this filter in UpperFilters for Serial class. No more SCM.

On startup, your filter will be a do-nothing passthru, which incurs nearly no
overhead, so there is no need to unload it. Then, when you will need the
functionality, turn it on by IOCTL. Turn it off by other IOCTL.

--
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
maxim@storagecraft.com
http://www.storagecraft.com



Re: Serial Upper Filter Driver Help Required by OldCodger101

OldCodger101
Wed Sep 29 11:04:17 CDT 2004

"Maxim S. Shatskih" <maxim@storagecraft.com> wrote in message news:<euXT2bcpEHA.3712@TK2MSFTNGP15.phx.gbl>...
> > MUST call it in MN_REMOVE_DEVICE - why?
> >
> > This driver is dynamically loaded by it's associated application by
> > means of the Service Control Manager then "started" (attached to the
> > correct COM port)
>
> Do you mean that you load the driver by SCM, and attach it to PnP stacks? This
> is really a way of having problems.

Yes. OpenSCManager, CreateService and StartService in the application
gets the driver running. This calls the DriverEntry function which
calls Addevice as per Walt Oney's PNPMON sample. AddDevice is not used
at any other time.

> Either is your driver a WDM PnP driver, which is built with DRIVERTYPE=WDM
> (this sets the header bit in a SYS binary, which later influences some power
> management code) and has a AddDevice routine. Such a driver must not be loaded
> by SCM, and, more so, cannot be loaded that way. It must be properly registered
> for the proper devnodes - if we are speaking about serial port filter, then add
> UpperFilters value to Serial class GUID.
>
> This gives you a lot, for instance, auto-loading your driver for all serial
> ports appeared on the machine, including USB ones, Bluetooth ones and so on.

Well that would be useful I must admit.

> Or - your driver has nothing to do with PnP, has no AddDevice and is loaded by
> SCM. Then forget about attaching to PnP stacks. You can only use them as a
> client, not intruding inside them as a filter.

I am not sure this is correct but as this is my first driver project
my knowledge is practically zero.

My "start" ioctl gets a pointer to the file object whose name is
passed in the SystemBuffer, ie "\??\COM4" and attaches my driver to
the stack with AttachDeviceToDeviceStack and then dereferences the
file pointer so the serial port is free again. This does work and when
a 2nd application (ie HyperTerminal) opens the port I can see the read
and write requests going through my driver.

> >and "stopped" (detached) by means of special IOCTLS
> > sent via the DeviceIoControl function.
>
> A way of having hard to debug crashes. For instance, it is nearly impossible to
> synchronize this "detach IOCTL" with other IRPs. And, more so - what if there
> is one more filter above you? A crash for sure. 100%. So, such code will
> inevitably have interop issues with other software.

In this case the application is for internal engineering test use only
and there will only ever be one other device above my driver and that
will be the application under test.

> >The device will never be
> > "removed" so why can't I detach the driver dynamically myself?
>
> Because you don't know whether there are more filters above, and if it is so -
> then a crash.
>
> >There are commercial products that I am sure use this same method
>
> So what? There are lots of misdesigned badly written software in the world.
>
> > successfully open the port from another applciation (Hyperterminal),
> > but when I detach the driver the port is no longer available, I have
> > not found the reason for this yet
>
> This is because you're moving in a wrong direction.
>
> Write a WDM PnP filter driver - it's very easy (by far easier then a function
> driver), use KBDFILTR as a sample and throw away all code related to keyboard
> and i8042 hooks. There are possibly even the pure WDM PnP filter samples in the
> DDK - not related to keyboard.
>
> The way to do is:

I am looking at this method now - thanks for your very detailed reply,
I will post back here how I get on.

<snip>

> On startup, your filter will be a do-nothing passthru, which incurs nearly no
> overhead, so there is no need to unload it. Then, when you will need the
> functionality, turn it on by IOCTL. Turn it off by other IOCTL.

This is also an interesting idea.

Many thanks Maxim.

Regards

Alasdair

Re: Serial Upper Filter Driver Help Required by Maxim

Maxim
Sat Oct 02 02:29:03 CDT 2004

> > On startup, your filter will be a do-nothing passthru, which incurs nearly
no
> > overhead, so there is no need to unload it. Then, when you will need the
> > functionality, turn it on by IOCTL. Turn it off by other IOCTL.
>
> This is also an interesting idea.

This is a mainstream in filter driver writing.

--
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
maxim@storagecraft.com
http://www.storagecraft.com