Help NDIS-WDM for serial port - IoCallDriver fails with accessdenied

Hi,
I am writing NDIS/WDM driver for serial port. Since I am writing driver
not as part of PnP stack I am calling IoGetDeviceObjectPointer with
FILE_ALL_ACCESS as ACCESS_MASK.

Using DeviceObject ptr I am able to configure the serial port(baud rate etc,.).
The problem I am facing is in send routine while trying to forward data
to serial port.

  1. when I call IoBuildAsynchronousFsdRequest with MajorFunction as IRP_MJ_WRITE
    it is never coming out of this call.

  2. I tried to allocate an IRP by IoAllocateIrp and Initialised the Irp to send data
    the IoCallDriver is returning with status access denied. When I observe in Portmon
    I am able to see IRP_MJ_CREATE Access Denied. Why am I getting IRP_MJ_CREATE when
    I try to write.

(11:59:54 AM services.exe IRP_MJ_CREATE Serial0 ACCESS DENIED Options: Supersede)

I have listed the code below. My doubt is when I am able to send
IoCtl requests why I am not able to send send request. Is there anything
wrong with the way I am construting the Irp.

Can anybody help on this?

Thank you,
Vamshi

irp_W = IoAllocateIrp((Device->pSerialDevObject->StackSize + 1), FALSE);
/*
irp_W = IoBuildAsynchronousFsdRequest(
IRP_MJ_WRITE,
Device->pSerialDevObject,
LocalPacketBuffer,
totalBytes,
NULL, //&ByteOffset,
&IoStatusBlock);
*/
if(irp_W != NULL)
{
irp_W->AssociatedIrp.SystemBuffer = LocalPacketBuffer;
pIrpStackLoc = IoGetCurrentIrpStackLocation(irp_W);
pIrpStackLoc->MajorFunction = IRP_MJ_WRITE;
pIrpStackLoc->Parameters.Write.Length = totalBytes;
DbgPrint(“MySend : Write Data IRP build was successful…”);
IoSetCompletionRoutine( irp_W,
WriteCompletionRoutine,
Device->pSerialDevObject,
TRUE,
TRUE,
TRUE);

}
else
{
DbgPrint(“MySend : Write Data IRP build FAILED…”);
status = STATUS_UNSUCCESSFUL;
goto done;
}

status = IoCallDriver( Device->pSerialDevObject, irp_W);

After allocating the IRP, you have at least to intialize it (
IoInitializeIRP ). This will probably solve all of the troubles.
ACCESS_DENIED is returned by the Serial Driver if one tries to open the
same device more than once at the same time.

> After allocating the IRP, you have at least to intialize it (

IoInitializeIRP ). This will probably solve all of the troubles.

Not so. IoAllocateIrp does NOT require IoInitializeIrp.
IoInitializeIrp is used only if you allocate the IRP from your own
memory.

Max

Hi Max,

The NT40 DDK help file explicitely states :

IoAllocateIrp ( Comments ):


An intermediate or highest-level driver can call IoAllocateIrp to create
IRPs for requests it sends to lower-level drivers. Such a driver must
initialize the IRP and must set its IoCompletion routine in the IRP it
creates so the caller can dispose of the IRP when lower-level drivers have
completed processing of the request.

IoInitializeIrp ( Comments ) :


If a driver calls IoAllocateIrp, it also must call IoInitializeIrp with
the same StackSize value and the pointer returned by IoAllocateIrp.

Are these statements superseded, or am I interpreting them falsely ?

Christiaan

Hi,

I think I need not call IoInitialize as 2000 ddk says “An IRP allocated by
IoAllocateIrp must not be passed to IoInitializeIrp”.

My Problem is when I call IoCallDriver with a device object pointer
obtained from IoGetDeviceObjectPtr,
to send a write Irp ACESS_DENIED is coming.
As you have pointed out serial driver gives ACCESS_DENIED when one tries
to open more than once.

When I try to send write Irp I see Create Irp(in portmon) is being sent
and is resulting in ACCESS_DENIED.
I don’t know why a create Irp is going when I am trying to send write Irp.

Can any body give the reason why this is happening?

Hi,

I found one thing missing, not too sure whether it matters. Try setting
the DeviceObject for the IRP Stack Location …

pIrpStackLoc->DeviceObject = Device->pSerialDevObject;

As I mentioned, not sure, but in one of my previous driver I remember
using this.

Regards,
Rajiv.

Yes I have done this initialisation too.
But it is resulting in the same error(ACCESS_DENIED).

Hi,

I am writing NDIS/WDM driver for serial port. Since I am
writing driver
not as part of PnP stack I am calling IoGetDeviceObjectPointer with
FILE_ALL_ACCESS as ACCESS_MASK.

Using DeviceObject ptr I am able to configure the serial
port(baud rate etc,.).

the IoCallDriver is returning with status access denied.
When I observe in Portmon
I am able to see IRP_MJ_CREATE Access Denied. Why am I
getting IRP_MJ_CREATE when
I try to write.

I found a similar problem with a filter driver above a serial (COMx)
port.
In my first (NT4) implementation all worked fine, but trying to use it
as
a legacy driver under Win2000 gave me the same problem you noticed
(ACCESS
DENIED when trying to write to the underlying COMx port, with an extra
IRP_MJ_CREATE sent down and failing before the write)

After a lot of trials, I’ve found that the only way to solve my problem
was
to move my attaching to the underlying device object from the
DriverEntry
to a custom DeviceIOControl, so changing the context the attaching
happens
into (I call my custom DeviceIOControl from a service App).

Hope this can help

Carlo

> IoInitializeIrp ( Comments ) :


If a driver calls IoAllocateIrp, it also must call IoInitializeIrp
with
the same StackSize value and the pointer returned by IoAllocateIrp.

Documentation bug fixed in later versions:

“IoAllocateIrp automatically initializes the IRP’s members. Do not use
IoInitializeIrp to initialize the IRP before its first use. (You can
use IoInitializeIrp to reuse an IRP that you have already used under
certain special circumstances. See Reusing IRPs for details.)”

Max