Inine.
-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Bill McKenzie
Sent: Saturday, January 26, 2008 1:20 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Disk accesses
> so we all just have to live with it
I don’t mind that we have a legacy situation, but it might be helpful to
know exactly what we have to live with.
> IOCTL_SCSI_EXECUTE_* is set in the stack location for an IRP_MJ_SCSI to
> (a) allow someone handling
> IRP_MJ_INTERNAL_DEVICE_CONTROL to differentiate between the two
Except that it isn’t. I see numerous IRP_MJ_SCSI, or
See the note after that where I mention that it’s not consistently used.
There is not a good way to distinguish between IRP_MJ_INTERNAL_DEVICE_CONTROL and IRP_MJ_SCSI. This is the legacy situation. There are still old class and filter drivers out there that don’t know to set IOCTL_SCSI_EXECUTE_* and there are probably monolithic port drivers that don’t bother to check for it. In general if you’re in a storage stack you don’t mix internal ioctls and SCSI irps … it’s the safest policy.
Failing that you can check the OutputBufferLength to see if it’s unusually large. No I don’t have a good definition of “unusually large” but I don’t usually see 2GB+ I/O control buffers. Like most heurstics this will screw you when it’s wrong, but if you’re in the realm of guessing it’s one approach.
>and (b) to provide some indicator of which direction the SRB is
>transferring data.
>Its use isn’t particularly consistent …
With all the documentation that is quite a surprise 
Even with documentation it wouldn’t help that much. There are legacy drivers that don’t set this value or don’t look at this value so again … don’t mix internal IOCTL and SCSI requests.
>They come with SCSI_PASS_THROUGH/SCSI_PASS_THROUGH_DIRECT structures so as
>not to expose SRB to user-mode and so as to avoid
>validating SRBs which might come from user-mode. Besides, how is a user
>mode component going to provide a value like OriginalIrp
I guess what I would have expected here is the IO manager to do a similar
job as it does for other I/O requests. I mean, IRPs aren’t exposed to
user-mode either, but buffers are validated and IRPs created for
DeviceIoControl calls. I would expect the IO Manager to see that a
SCSI_PASS_THROUGH_* request is coming down, and to create an SRB on behalf
of the driver to keep the code paths sane and clean.
The I/O manager does for this IOCTL exactly what it does for all other I/O requests - it makes an IRP and tracks the buffers and then sends it to the drivers. The I/O manager doesn’t care what I/O control code is sent and doesn’t do anything magical as a result of it for any I/O request.
What also added to my confusion is three separate CD-ROM burning
applications all burning the same data to writable CD-R media, but all using
different I/O request paths. It makes one wonder why, thus my question.
They all come up with slightly different architectures. Some folks don’t want to write a kernel driver at all. Some want a kernel driver that does all the work because they think this is faster. Some want a driver that’s low in the stack because they don’t want another driver to interfere with them. Some like to add copy protection gunk into your system. This isn’t that different than taking any random N programs that theoretically do the same thing and analyzing how they get there.
“Peter Wieland” wrote in message
news:xxxxx@ntdev…
IRP_MJ_SCSI == IRP_MJ_INTERNAL_DEVICE_CONTROL. This is easily determined by
looking at the headers. No SCSI shouldn’t have its own IRP MJ code, and no
it shouldn’t reuse a number from an existing one. But it’s been that way
since I joined MS (and I tried to change it once … not possible without
breaking everyone doing storage) and so we all just have to live with it.
Someone decided we needed a MJ code for SCSI requests. I suspect
IRP_MJ_INTERNAL_DEVICE_CONTROL was reused to avoid the cost of an additional
PVOID per driver object (which at the time would have been an issue).
IOCTL_SCSI_EXECUTE_* is set in the stack location for an IRP_MJ_SCSI to (a)
allow someone handling IRP_MJ_INTERNAL_DEVICE_CONTROL to differentiate
between the two and (b) to provide some indicator of which direction the SRB
is transferring data. Its use isn’t particularly consistent … I think of
it as more of a debugging aid but I see that some of our drivers (like the
RAMDISK driver) use it to decide if the SRB in question is a read/write type
command or one of those strange SCSI commands like REQUEST_SENSE which
require more complex emulation. I think using the CDB code would have been
a much better idea.
IRP_MJ_SCSI comes with an SRB.
IOCTL_SCSI_PASS_THROUGH and IOCTL_SCSI_PASS_THROUGH_DIRECT are to send SCSI
requests from user-mode. They come with
SCSI_PASS_THROUGH/SCSI_PASS_THROUGH_DIRECT structures so as not to expose
SRB to user-mode and so as to avoid validating SRBs which might come from
user-mode. Besides, how is a user mode component going to provide a value
like OriginalIrp. IOCTL_SCSI_PASS_THROUGH is a buffered operation, while
IOCTL_SCSI_PASS_THROUGH_DIRECT direct maps the data transfer. They’re
separate control codes because they are - I suppose a flag in the
PASS_THROUGH structure could have contained the transfer mode … would that
make you happier?
So there are two ways to send a SCSI request. One for kernel-mode
components (IRP_MJ_SCSI) and one for user-mode components
(IOCTL_SCSI_PASS_THROUGH[_DIRECT]). If you want to convert a pass-through
command to a IRP_MJ_SCSI command it’s pretty straight-forward to make an SRB
and send it down. I bet you could even do it without “duplicat[ing] code
all over” if you tried. This is how the SCSI port drivers deal with it -
validate the parameters, build an SRB and then push that in through the code
that handles SRBs.
-p
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Bill McKenzie
Sent: Friday, January 25, 2008 3:13 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Disk accesses
Can someone explain why there are so many different ways to send the same
SCSI request to a disk?? IRP_MJ_SCSI w/ no or some undocumented IOCT codes,
or IRP_MJ_INTERNAL_DEVICE_CONTROL (or is that actually IRP_MJ_SCSI again??)
w/: IOCTL_SCSI_EXECUTE_IN, IOCTL_SCSI_PASS_THROUGH, or
IOCTL_SCSI_PASS_THROUGH_DIRECT.
Oh, and you may get a SCSI_REQUEST_BLOCK or no wait is that a
SCSI_PASS_THROUGH_DIRECT structure? I know let’s not make them overlap so
everyone can just duplicate code all over.
I know I am probably late to the game on this…but is there a rhyme or
reason to this lovely architecture? Did I miss some documentation
somewhere?
I would love to know the why of all of this.
Bill M.
—
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
—
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