While trying to understand how different buffering methods work, I
came across an odd IOCTL, IOCTL_CDROM_RAW_READ. The DDK description
of it seems normal at first. There's Irp->AssociatedIrp.SystemBuffer
for buffered input and Irp->MdlAddress for direct output, and the
IOCTL is defined in the DDK headers to use METHOD_OUT_DIRECT.

That's fine, but the description also says that if the IOCTL is sent
from kernel mode then Type3InputBuffer should be used for input, and
it's not even clear what should be used for output. Type3InputBuffer
is for METHOD_NEITHER, except the IOCTL is already using
METHOD_OUT_DIRECT.

How can an IOCTL like this that mixes two different buffering methods
be sent, and how is the receiver supposed to know which method was
used by the sender?

Re: Two buffering methods for one IOCTL? by Maxim

Maxim
Thu Oct 12 16:13:37 CDT 2006

METHOD_BUFFERED: ->AssociatedIrp.SystemBuffer for In and Out

METHOD_OUT_DIRECT: ->AssociatedIrp.SystemBuffer for In, ->MdlAddress for
Out

METHOD_IN_DIRECT: no Out, Out is in fact one more In, consider this to be
"write with additional info". ->AssociatedIrp.SystemBuffer for In, ->MdlAddress
for Out which is 2nd In (main data).

METHOD_NEITHER: ->Parameters.DeviceControl.Type3InputBuffer for In,
>UserBuffer for Out.

I think that ->UserBuffer is always valid and is always Out, but I would
not rely on this.

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

<BubbaGump> wrote in message news:679ti29e9c9jlk8immfea58vvl12q00ua8@4ax.com...
> While trying to understand how different buffering methods work, I
> came across an odd IOCTL, IOCTL_CDROM_RAW_READ. The DDK description
> of it seems normal at first. There's Irp->AssociatedIrp.SystemBuffer
> for buffered input and Irp->MdlAddress for direct output, and the
> IOCTL is defined in the DDK headers to use METHOD_OUT_DIRECT.
>
> That's fine, but the description also says that if the IOCTL is sent
> from kernel mode then Type3InputBuffer should be used for input, and
> it's not even clear what should be used for output. Type3InputBuffer
> is for METHOD_NEITHER, except the IOCTL is already using
> METHOD_OUT_DIRECT.
>
> How can an IOCTL like this that mixes two different buffering methods
> be sent, and how is the receiver supposed to know which method was
> used by the sender?
>


Re: Two buffering methods for one IOCTL? by BubbaGump

BubbaGump
Thu Oct 12 16:33:21 CDT 2006

Yes, that all makes sense, but I'm asking a more subtle question.

The #define for an IOCTL code only specifies one of these methods.
What happens if the documentation for an IOCTL specifies two of them?
In that case how can the receiving driver know which one was used to
send the IOCTL? How can the sending driver send such an IOCTL? (it
doesn't seem compatible with DeviceIoControl or
IoBuildDeviceIoControlRequest)




On Fri, 13 Oct 2006 01:13:37 +0400, "Maxim S. Shatskih"
<maxim@storagecraft.com> wrote:

> METHOD_BUFFERED: ->AssociatedIrp.SystemBuffer for In and Out
>
> METHOD_OUT_DIRECT: ->AssociatedIrp.SystemBuffer for In, ->MdlAddress for
>Out
>
> METHOD_IN_DIRECT: no Out, Out is in fact one more In, consider this to be
>"write with additional info". ->AssociatedIrp.SystemBuffer for In, ->MdlAddress
>for Out which is 2nd In (main data).
>
> METHOD_NEITHER: ->Parameters.DeviceControl.Type3InputBuffer for In,
>>UserBuffer for Out.
>
> I think that ->UserBuffer is always valid and is always Out, but I would
>not rely on this.


Re: Two buffering methods for one IOCTL? by Peter

Peter
Thu Oct 12 20:14:17 CDT 2006

Check RequestorMode in the IRP.

-p

"BubbaGump" wrote in message
news:2lcti25dbi9tnlvmk01n3h03jl0ed06vbj@4ax.com...
> Yes, that all makes sense, but I'm asking a more subtle question.
>
> The #define for an IOCTL code only specifies one of these methods.
> What happens if the documentation for an IOCTL specifies two of them?
> In that case how can the receiving driver know which one was used to
> send the IOCTL? How can the sending driver send such an IOCTL? (it
> doesn't seem compatible with DeviceIoControl or
> IoBuildDeviceIoControlRequest)
>
>
>
>
> On Fri, 13 Oct 2006 01:13:37 +0400, "Maxim S. Shatskih"
> <maxim@storagecraft.com> wrote:
>
>> METHOD_BUFFERED: ->AssociatedIrp.SystemBuffer for In and Out
>>
>> METHOD_OUT_DIRECT: ->AssociatedIrp.SystemBuffer for In, ->MdlAddress
>> for
>>Out
>>
>> METHOD_IN_DIRECT: no Out, Out is in fact one more In, consider this to
>> be
>>"write with additional info". ->AssociatedIrp.SystemBuffer for
>>In, ->MdlAddress
>>for Out which is 2nd In (main data).
>>
>> METHOD_NEITHER: ->Parameters.DeviceControl.Type3InputBuffer for In,
>>>UserBuffer for Out.
>>
>> I think that ->UserBuffer is always valid and is always Out, but I
>> would
>>not rely on this.
>


Re: Two buffering methods for one IOCTL? by BubbaGump

BubbaGump
Thu Oct 12 20:59:50 CDT 2006

Oh, I didn't even notice that field. Okay, that should take care of
the receiver.

What about the sender? I'm confused why an IOCTL would use
Type3InputBuffer for input but still use MdlAddress for output, if I
read the description of IOCTL_CDROM_RAW_READ right. Another IOCTL
that does this is IOCTL_HID_GET_INDEXED_STRING. I don't need to use
these IOCTLs, but I'm trying to understand what general rules they
imply.




On Thu, 12 Oct 2006 18:14:17 -0700, "Peter Wieland [MSFT]"
<peterwie@online.microsoft.com> wrote:

>Check RequestorMode in the IRP.
>
>-p
>
>"BubbaGump" wrote in message
>news:2lcti25dbi9tnlvmk01n3h03jl0ed06vbj@4ax.com...
>> Yes, that all makes sense, but I'm asking a more subtle question.
>>
>> The #define for an IOCTL code only specifies one of these methods.
>> What happens if the documentation for an IOCTL specifies two of them?
>> In that case how can the receiving driver know which one was used to
>> send the IOCTL? How can the sending driver send such an IOCTL? (it
>> doesn't seem compatible with DeviceIoControl or
>> IoBuildDeviceIoControlRequest)
>>
>>
>>
>>
>> On Fri, 13 Oct 2006 01:13:37 +0400, "Maxim S. Shatskih"
>> <maxim@storagecraft.com> wrote:
>>
>>> METHOD_BUFFERED: ->AssociatedIrp.SystemBuffer for In and Out
>>>
>>> METHOD_OUT_DIRECT: ->AssociatedIrp.SystemBuffer for In, ->MdlAddress
>>> for
>>>Out
>>>
>>> METHOD_IN_DIRECT: no Out, Out is in fact one more In, consider this to
>>> be
>>>"write with additional info". ->AssociatedIrp.SystemBuffer for
>>>In, ->MdlAddress
>>>for Out which is 2nd In (main data).
>>>
>>> METHOD_NEITHER: ->Parameters.DeviceControl.Type3InputBuffer for In,
>>>>UserBuffer for Out.
>>>
>>> I think that ->UserBuffer is always valid and is always Out, but I
>>> would
>>>not rely on this.
>>


Re: Two buffering methods for one IOCTL? by Tim

Tim
Sat Oct 14 00:53:30 CDT 2006

BubbaGump <> wrote:

>Oh, I didn't even notice that field. Okay, that should take care of
>the receiver.
>
>What about the sender? I'm confused why an IOCTL would use
>Type3InputBuffer for input but still use MdlAddress for output, if I
>read the description of IOCTL_CDROM_RAW_READ right. Another IOCTL
>that does this is IOCTL_HID_GET_INDEXED_STRING. I don't need to use
>these IOCTLs, but I'm trying to understand what general rules they
>imply.

There are no completely general rules. If an ioctl comes from user-mode,
then the I/O manager will always use the method in the low-order two bits
of the ioctl code. If the ioctl comes from kernel-mode, then all bets are
off. You have to have documentation.
--
- Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Re: Two buffering methods for one IOCTL? by BubbaGump

BubbaGump
Sat Oct 14 09:03:55 CDT 2006

On Fri, 13 Oct 2006 22:53:30 -0700, Tim Roberts <timr@probo.com>
wrote:

>BubbaGump <> wrote:
>
>>Oh, I didn't even notice that field. Okay, that should take care of
>>the receiver.
>>
>>What about the sender? I'm confused why an IOCTL would use
>>Type3InputBuffer for input but still use MdlAddress for output, if I
>>read the description of IOCTL_CDROM_RAW_READ right. Another IOCTL
>>that does this is IOCTL_HID_GET_INDEXED_STRING. I don't need to use
>>these IOCTLs, but I'm trying to understand what general rules they
>>imply.
>
>There are no completely general rules. If an ioctl comes from user-mode,
>then the I/O manager will always use the method in the low-order two bits
>of the ioctl code. If the ioctl comes from kernel-mode, then all bets are
>off. You have to have documentation.

I might be able to understand if the kernel-mode case simply used
Type3InputBuffer as a direct pointer, but it looks like it uses both
Type3InputBuffer and MdlAddress. What's the use of an MDL for sending
data from one kernel-mode component to another?


Re: Two buffering methods for one IOCTL? by Mark

Mark
Sat Oct 14 11:39:51 CDT 2006

On Sat, 14 Oct 2006 10:04:01 -0400, BubbaGump <> wrote:


>
>I might be able to understand if the kernel-mode case simply used
>Type3InputBuffer as a direct pointer, but it looks like it uses both
>Type3InputBuffer and MdlAddress. What's the use of an MDL for sending
>data from one kernel-mode component to another?


The input buffer is a control structure describing how the data ought
to be transferred. The data (in Irp->MdlAddress) is contained in an
MDL for two reasons: 1) so that it is locked down, 2) so that it can
be DMA'd by the low level scsiport driver, which requires Mdl
requests.

The use of an MDL for sending data from one kernel mode component to
another is almost identical as the use for doing this from user mode.
Kernel data is pageable, right? The other use is that ultimately the
data is going to go off to hardware (in many cases) and the hardware
driver probably has a direct-io requirement. The only major difference
is that the page mappings for kernel mode are shared across all kernel
mode threads.


=====================
Mark Roddy DDK MVP
Windows Vista/2003/XP/2000 Consulting
Device and Filesystem Drivers
Hollis Technology Solutions 603-321-1032
www.hollistech.com

Re: Two buffering methods for one IOCTL? by BubbaGump

BubbaGump
Sat Oct 14 12:18:39 CDT 2006

On Sat, 14 Oct 2006 12:39:51 -0400, Mark Roddy <markr@hollistech.com>
wrote:

>On Sat, 14 Oct 2006 10:04:01 -0400, BubbaGump <> wrote:
>
>
>>
>>I might be able to understand if the kernel-mode case simply used
>>Type3InputBuffer as a direct pointer, but it looks like it uses both
>>Type3InputBuffer and MdlAddress. What's the use of an MDL for sending
>>data from one kernel-mode component to another?
>
>
>The input buffer is a control structure describing how the data ought
>to be transferred. The data (in Irp->MdlAddress) is contained in an
>MDL for two reasons: 1) so that it is locked down, 2) so that it can
>be DMA'd by the low level scsiport driver, which requires Mdl
>requests.
>
>The use of an MDL for sending data from one kernel mode component to
>another is almost identical as the use for doing this from user mode.
>Kernel data is pageable, right? The other use is that ultimately the
>data is going to go off to hardware (in many cases) and the hardware
>driver probably has a direct-io requirement. The only major difference
>is that the page mappings for kernel mode are shared across all kernel
>mode threads.

Okay, the MDL makes sense to keep with the conventions of the DMA API.
Is Type3InputBuffer used simply to avoid the small copy that
SystemBuffer would imply?

So, I guess these types of IOCTLs won't work with
IoBuildDeviceIoControlRequest. Would they be done using
IoAllocateIrp, IoAllocateMdl, and MmBuildMdlForNonPagedPool?


Re: Two buffering methods for one IOCTL? by Mark

Mark
Sat Oct 14 14:13:38 CDT 2006

On Sat, 14 Oct 2006 13:18:46 -0400, BubbaGump <> wrote:

>On Sat, 14 Oct 2006 12:39:51 -0400, Mark Roddy <markr@hollistech.com>
>wrote:
>
>>On Sat, 14 Oct 2006 10:04:01 -0400, BubbaGump <> wrote:
>>
>>
>>>
>>>I might be able to understand if the kernel-mode case simply used
>>>Type3InputBuffer as a direct pointer, but it looks like it uses both
>>>Type3InputBuffer and MdlAddress. What's the use of an MDL for sending
>>>data from one kernel-mode component to another?
>>
>>
>>The input buffer is a control structure describing how the data ought
>>to be transferred. The data (in Irp->MdlAddress) is contained in an
>>MDL for two reasons: 1) so that it is locked down, 2) so that it can
>>be DMA'd by the low level scsiport driver, which requires Mdl
>>requests.
>>
>>The use of an MDL for sending data from one kernel mode component to
>>another is almost identical as the use for doing this from user mode.
>>Kernel data is pageable, right? The other use is that ultimately the
>>data is going to go off to hardware (in many cases) and the hardware
>>driver probably has a direct-io requirement. The only major difference
>>is that the page mappings for kernel mode are shared across all kernel
>>mode threads.
>
>Okay, the MDL makes sense to keep with the conventions of the DMA API.
>Is Type3InputBuffer used simply to avoid the small copy that
>SystemBuffer would imply?
>
>So, I guess these types of IOCTLs won't work with
>IoBuildDeviceIoControlRequest. Would they be done using
>IoAllocateIrp, IoAllocateMdl, and MmBuildMdlForNonPagedPool?

The ad hoc structuring of this particular IOCTL is hideous and
indefensible. The IOCTL should use one of the standard mechanisms
appropriately instead of having a secret understanding. Having a
control structure and a data buffer is a standard technique for IOCTL
operations and does not require this sort of hackery.



=====================
Mark Roddy DDK MVP
Windows Vista/2003/XP/2000 Consulting
Device and Filesystem Drivers
Hollis Technology Solutions 603-321-1032
www.hollistech.com