Michael,
In addition to what has already been mentioned, one of the easiest ways
to distinguish what one is doing (and whether one is a PDO or FDO) is to
make the device extension for the PDO’s and FDO’s in the bus driver have
a common part at the beginning (I opted for a flags field). Of course,
the exact processing for read/write IRP’s depends on exactly what you
want to do, but in my case, read / write IRP’s could safely be ignored.
So, when I got a read / write IRP, I got hold of the extension, and
looked at the common part before deciding what to do with it:
NTSTATUS MTF_DispatchRead(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
PDEV_EXT_COMMON pDEC;
KdPrint4((DRIVERNAME “: MTF_DispatchRead\n”));
pDEC = pDeviceObject->DeviceExtension;
if (!(pDEC->flags & FLAGS_IS_PDO))
{
return MDX_DispatchRead(pDeviceObject, pIrp);
}
else
{
if (!MTF_IsLivingPDO(pDeviceObject))
{
return MTF_CompleteRequest(pIrp, STATUS_NO_SUCH_DEVICE);
}
return MTF_PDO_Ignore(pDeviceObject, pIrp);
}
}
PDEV_EXT_COMMON being the common part of the device extension for FDO’s
and PDO’s.
MH.
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Michael Becker
Sent: 20 May 2005 20:20
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Can unnamed PDOs get IOCTLs, etc.
Thanks for the reply Doron!
Please forgive this long reply, but I really want to see if I understand
the concepts here. If I screw anything up, don’t hesitate to tell me.
In DriverEntry(), we set-up pointers to functions for the major entry
points into the Driver. In IoCreateDevice(), we not only create a
DeviceObject, but we also associate this created DeviceObject with the
DriverObject. If “someone” makes an IO request of the DeviceObject,
then the corresponding DriverObject Dispatch function is called.
Therefore, when a Lower Driver creates PDOs, it is associating these
PDOs with its DriverObject - if “someone” tries to “IRP_MJ_READ” a PDO,
then the DispatchRead() function from the Lower Driver will be called
with the PDO as the DeviceObject.
However, IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_DEVICE_CONTROL are not called
by default from anything in the kernel, unlike IRP_MJ_PNP and
IRP_MJ_POWER. An application or some non-intrinsic kernel driver (the
Higher Level Driver) would have to “explicitly” send a
IRP_MJ_DEVICE_CONTROL to the PDO Device to make this happen.
So the only way that the lower level driver could get a
IRP_MJ_DEVICE_CONTROL from its PDO DeviceObject is if the FDO sitting on
top of it sent it down the stack? (Because we don’t create any symlinks
for these PDOs to be accessible from usermode).
Only Way:
================ Upper Driver ========================
±-----------+ ±-----------+
| Child FDO | | Child FDO | …
±-----------+ ±-----------+
| |
|“forwarding IRP” |
|“down the stack” |
| |
| |
================ Lower Driver ========================
| |
| |
V V
±-----------+ ±-----------+ ±-----------+
| Parent FDO | | Parent PDO | | Parent PDO | …
±-----------+ ±-----------+ ±-----------+
BTW: The checking that is occurring looks like it is verifying that
these requests are from the FDO and not the PDO. But what it’s also
doing is substituting the FDO DeviceExtension saved from a global
variable in the driver if the IO request comes from the PDO instead of
just failing the IRP. And since we also wrote and control the Higher
Level Driver, I can see that for IRP_MJ_READ, IRP_MJ_DEVICE_CONTROL, and
IRP_MJ_WRITE the Higher Driver is never forwarding or passing down the
IRP. Instead it is calling an interface function.
So, if I’m right, then I can safely fail IRPs that come in from the PDOs
and get rid of the global variable, since this should never happen
(pending bugs of course).
Again, if I have screwed something up in my understanding, please feel
free to let me know.
Thanks Again Everyone!
-Mike
Doron Holan wrote:
What a PDO receives (outside of pnp, power, wmi) is up to the
PDO to
define. If the FDO can send i/o to the PDO and the PDO
processes it,
then it is allowed, otherwise it is not.
Are you sure the code is checking to make sure it is the lowest
device
in the stack vs distinguishing whether the I/O is sent the PDO
or FDO?
If it that is the logic, I would keep it. It is good defensive
programming, otherwise I/O sent to the PDO will be processed as
if sent
to the FDO, in which case the wrong device extension will be
used and
very bad things could happen. If the PDO just fails the i/o,
the logic
is pretty simple (set status to failure, complete the request,
return
status).
d
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Michael
Becker
Sent: Friday, May 20, 2005 8:22 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] Can unnamed PDOs get IOCTLs, etc.
Hi All,
I am working on maintaining a driver not written by me, and as I
am
trying to understanding it, I came across a question(s) that I
haven’t
been able to find an answer to or an understanding of in the
newsgroups
or DDK.
This driver is based on the multifunction driver from Oney’s
book. It
creates a named Device Object in AddDevice(), and also creates
17
auto-named PDOs during (IRP_MJ_PNP, IRP_MN_START_DEVICE)
processing.
There is a separate child driver that sits on top of this driver
and
creates 17 FDOs, with device names that the application is
using. It
also appears that these child devices/FDOs/the Child Driver uses
interfaces to the parent driver via (IRP_MJ_PNP,
IRP_MN_QUERY_INTERFACE).
Ok. Now that all of the background is out of the way (I think),
my
question is, “Is there anyway that the Parent created PDOs (the
17)
could get passed in to the Read/Write/Ioctl Driver Dispatch
routines?”
I think that this should never happen - but am absolutely sure -
because
I don’t really have a firm understanding of PDO / FDO / Bus
Driver
relations yet.
Why do I care? Because there is lots of code present in this
driver
which makes a big deal about checking to verify that the
DeviceObject
passed to DispatchRead/DispatchIoctl/etc is in fact the lowest
DeviceObject. And I would like to remove it to simplify the
driver -
but only if it makes sense to do so.
Thank You all in advance for reading this and any help you may
be able
to give!
Best Regards,
-Mike
PS:
If it helps, here is an example of one of the functions called
that
actually creates one of these PDO Devices:
NTSTATUS
CreateRaw( PDEVICE_EXTENSION devExt,
ULONG ChannelIndex)
{
//---------------------------------
NTSTATUS status;
PDEVICE_OBJECT Pdo;
PPDO_EXTENSION PdoExtension;
//---------------------------------
status = IoCreateDevice( devExt->DriverObject,
sizeof(PDO_EXTENSION),
NULL,
FILE_DEVICE_UNKNOWN,
FILE_AUTOGENERATED_DEVICE_NAME,
FALSE,
&Pdo);
if (!NT_SUCCESS(status)){
// Print out failure info here…
return (status);
}
PdoExtension = (PPDO_EXTENSION) Pdo->DeviceExtension;
PdoExtension->flags = ISPDO | ChannelIndex;
PdoExtension->DeviceObject = Pdo;
PdoExtension->Fdo = devExt->DeviceObject;
devExt->raw_device = Pdo;
Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
return (STATUS_SUCCESS);
}
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
You are currently subscribed to ntdev as:
xxxxx@windows.microsoft.com
To unsubscribe send a blank email to
xxxxx@lists.osr.com
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
You are currently subscribed to ntdev as: unknown lmsubst tag
argument: ‘’
To unsubscribe send a blank email to
xxxxx@lists.osr.com
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
You are currently subscribed to ntdev as: xxxxx@snellwilcox.com
To unsubscribe send a blank email to xxxxx@lists.osr.com
This email and any attachments is confidential, may be legally privileged and is intended for the use of the addressee only. If you are not the intended recipient, please note that any use, disclosure, printing or copying of this email is strictly prohibited and may be unlawful. If received in error, please delete this email and any attachments and confirm this to the sender.