32bit pointers for 64bit driver

Hello All!

We have a 32-bit application and 64-bit driver working together.
In some IOCTLs we have embedded pointers to user mode buffers.
How can we turn those 32bit pointers into 64bit pointers that our driver can use?

Can we just do it this way:
PTR32 p32 = ioctlStruct.pointer_to_buffer;
PTR64 p64 = (PTR64)p32;

or are other steps required?


Do you Yahoo!?
Yahoo! Mail is new and improved - Check it out!
http://promotions.yahoo.com/new_mail

The best way is to refactor the IOCTL set for the buffers to contain no
pointers.

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

----- Original Message -----
From: “Al Shatilo”
To: “Windows System Software Devs Interest List”
Sent: Monday, June 21, 2004 8:54 PM
Subject: [ntdev] 32bit pointers for 64bit driver

> Hello All!
>
> We have a 32-bit application and 64-bit driver working together.
> In some IOCTLs we have embedded pointers to user mode buffers.
> How can we turn those 32bit pointers into 64bit pointers that our driver can
use?
>
> Can we just do it this way:
> PTR32 p32 = ioctlStruct.pointer_to_buffer;
> PTR64 p64 = (PTR64)p32;
>
> or are other steps required?
>
>
>
> __________________________________
> Do you Yahoo!?
> Yahoo! Mail is new and improved - Check it out!
> http://promotions.yahoo.com/new_mail
>
> —
> Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as: xxxxx@storagecraft.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com

You cannot use user buffer pointers in kernel space (32 bit or 64 bit).

I would assume that when you get a user buffer pointer, you could use
IoAllocateMdl to create an MDL using the 32bit pointer, lock the pages using
MmProbeAndLockPages, and then use MmGetSystemAddressForMdlSafe to get a
kernel mode pointer. Make sure you probe & lock pages inside a try/except
block .

“Al Shatilo” wrote in message news:xxxxx@ntdev…
> Hello All!
>
> We have a 32-bit application and 64-bit driver working together.
> In some IOCTLs we have embedded pointers to user mode buffers.
> How can we turn those 32bit pointers into 64bit pointers that our driver
can use?
>
> Can we just do it this way:
> PTR32 p32 = ioctlStruct.pointer_to_buffer;
> PTR64 p64 = (PTR64)p32;
>
> or are other steps required?
>
>
>
> __________________________________
> Do you Yahoo!?
> Yahoo! Mail is new and improved - Check it out!
> http://promotions.yahoo.com/new_mail
>

cd wrote:
> You cannot use user buffer pointers in kernel space (32 bit or 64
> bit).

This is probably obvious, but it’s more accurate to say:

Non-top-level device objects and those that pend IRPs containing such
pointers cannot use user buffer pointers in kernel space.

While I wouldn’t call it good practice, if you create your own device
object, and user apps send it IOCTLs, and you handle them without
pending (entirely at PASSIVE_LEVEL), it’s perfectly possible to use
pointers to user buffers.

You better hope that no one filters your device object, though (or that
if they do, they are polite and follow the same rules).

I would assume that when you get a user buffer pointer, you could use
IoAllocateMdl to create an MDL using the 32bit pointer, lock the pages using
MmProbeAndLockPages, and then use MmGetSystemAddressForMdlSafe to get a
kernel mode pointer. Make sure you probe & lock pages inside a try/except
block .

“Al Shatilo” wrote in message news:xxxxx@ntdev…
>
>>Hello All!
>>
>>We have a 32-bit application and 64-bit driver working together.
>>In some IOCTLs we have embedded pointers to user mode buffers.
>>How can we turn those 32bit pointers into 64bit pointers that our driver
>
> can use?
>
>>Can we just do it this way:
>>PTR32 p32 = ioctlStruct.pointer_to_buffer;
>>PTR64 p64 = (PTR64)p32;
>>
>>or are other steps required?
>>
>>
>>
>> __________________________________
>>Do you Yahoo!?
>>Yahoo! Mail is new and improved - Check it out!
>>http://promotions.yahoo.com/new_mail
>>
>
>
>
>


…/ray..

Please remove “.spamblock” from my email address if you need to contact
me outside the newsgroup.

Ray Trent wrote:

cd wrote:
> You cannot use user buffer pointers in kernel space (32 bit or 64
> bit).

This is probably obvious, but it’s more accurate to say:

Non-top-level device objects and those that pend IRPs containing such
pointers cannot use user buffer pointers in kernel space.

While I wouldn’t call it good practice, if you create your own device
object, and user apps send it IOCTLs, and you handle them without
pending (entirely at PASSIVE_LEVEL), it’s perfectly possible to use
pointers to user buffers.

You better hope that no one filters your device object, though (or that
if they do, they are polite and follow the same rules).

[…]

Well, so far it should be clear for anyone with just the slightest
background in NT driver development.

And I guess most people agree that embedded pointers should be avoided
whenever possible, but sometimes they are very good for
performance/security (you can use buffered IO for the ‘command’
structure, but let the driver access data buffers directly).
So let’s just keep this point out of the discussion and concentrate on
the OP’s question:
How can you make use of an embedded pointer sent by a 32bit process
running under WOW64?

I’ve seen quite a few documents about porting drivers (and accompanying
user mode applications), and they all mention, in one way or another,
that you have to be careful when you have embedded pointers, because
void* means different things for 32bit and 64bit.
However, none of them showed any sample code where a 64bit driver
actually used a 32bit pointer.

My theory on this (I didn’t yet have the possibility to play with a
64bit system, so I couldn’t test my theory) is, that the user mode
application’s address space is mapped into kernel mode address space
starting from address 0, as it is the case for 32bit apps on 32bit
systems (and probably also for 64bit apps on 64bit systems).
At least that’s the way I would have done it.

(I definitely can’t believe that it’s not possible any more to use
embedded pointers, since this would break too many drivers.)

So if someone who is in the know could comment on this, I would
appreciate this (and the OP as well, I guess).

Best regards

Rolf Schäuble

Well, you can’t know what the best solution is, since you don’t know the
specifics of the OP’s driver. Actually, he might have a good reason to
use embedded pointers (well, at least I could imagine situations where
they would make sense). If used properly, there is no harm done using them.

I think it would be more helpful if someone who knows the details could
just answer the question, so we can all learn something.

Best regards

Rolf Schäuble

Maxim S. Shatskih wrote:

The best way is to refactor the IOCTL set for the buffers to contain no
pointers.

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

----- Original Message -----
From: “Al Shatilo”
> To: “Windows System Software Devs Interest List”
> Sent: Monday, June 21, 2004 8:54 PM
> Subject: [ntdev] 32bit pointers for 64bit driver
>
>
>
>>Hello All!
>>
>>We have a 32-bit application and 64-bit driver working together.
>>In some IOCTLs we have embedded pointers to user mode buffers.
>>How can we turn those 32bit pointers into 64bit pointers that our driver can
>
> use?
>
>>Can we just do it this way:
>>PTR32 p32 = ioctlStruct.pointer_to_buffer;
>>PTR64 p64 = (PTR64)p32;
>>
>>or are other steps required?
>>
>>
>>
>> __________________________________
>>Do you Yahoo!?
>>Yahoo! Mail is new and improved - Check it out!
>>http://promotions.yahoo.com/new_mail
>>
>>—
>>Questions? First check the Kernel Driver FAQ at
>
> http://www.osronline.com/article.cfm?id=256
>
>>You are currently subscribed to ntdev as: xxxxx@storagecraft.com
>>To unsubscribe send a blank email to xxxxx@lists.osr.com
>
>
>

“Rolf Schaeuble” wrote in message
news:xxxxx@ntdev…
>
> And I guess most people agree that embedded pointers should be avoided
> whenever possible, but sometimes they are very good for
> performance/security (you can use buffered IO for the ‘command’
> structure, but let the driver access data buffers directly).

Actually, security is one of the biggest problems with embedded drivers, it
is amazing
the number of ways people mess up the tests for validity of the buffers, and
as has
been commented the problems that can occur with kernel versus user buffers.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting

Don Burn wrote:

“Rolf Schaeuble” wrote in message
> news:xxxxx@ntdev…
>
>>And I guess most people agree that embedded pointers should be avoided
>>whenever possible, but sometimes they are very good for
>>performance/security (you can use buffered IO for the ‘command’
>>structure, but let the driver access data buffers directly).
>
>
> Actually, security is one of the biggest problems with embedded drivers, it
> is amazing
> the number of ways people mess up the tests for validity of the buffers, and
> as has
> been commented the problems that can occur with kernel versus user buffers.
>
>

However, for buffers that contain data that the driver does not
interpret but just transmit in one way or another, embedded pointers
should not do any harm.

Imagine an IOCTL structure like this:
struct MyIoctl
{
void* DataBuffer;
ULONG BufferLengt;
};

If this structure is transmitted to the driver via buffered IO, one way
for user mode to exploit the driver is not possible: changing the buffer
while the driver is accessing it.

As long as DataBuffer only contains arbitrary data that the driver has
to transmit to/from some hardware (or in case of a FS to read or write
it), then I don’t see much that can go wrong.
ProbleForRead/ProbeForWrite, followed by either accessing it in a
_try/_except block or building a MDL, should be perfectly fine.
(Before doing it in real code, I would have a look at some sample that I
know is doing it correctly :wink: )
If the driver interprets the data in DataBuffer, however, then of
course we might have yet another security problem.

I have to admit that my sample is pretty simple, but it should
illustrate my point.

Now back to the original question: If DataBuffer is a 32bit pointer, how
can a 64bit driver get access to the buffer?

Best regards

Rolf Schäuble

Please let me know your drivers that do this, I want to remove the security
holes from my
system. There is a heck of a lot of data validation you need to handle the
buffer pointer
and length combination correctly from all those nasty cases that can be
attacked from a
security point of view. The assumption that “don’t see much that can go
wrong” has
crashed more systems than I want to think about.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting

“Rolf Schaeuble” wrote in message
news:xxxxx@ntdev…
> Don Burn wrote:
>
> > “Rolf Schaeuble” wrote in message
> > news:xxxxx@ntdev…
> >
> >>And I guess most people agree that embedded pointers should be avoided
> >>whenever possible, but sometimes they are very good for
> >>performance/security (you can use buffered IO for the ‘command’
> >>structure, but let the driver access data buffers directly).
> >
> >
> > Actually, security is one of the biggest problems with embedded drivers,
it
> > is amazing
> > the number of ways people mess up the tests for validity of the buffers,
and
> > as has
> > been commented the problems that can occur with kernel versus user
buffers.
> >
> >
>
> However, for buffers that contain data that the driver does not
> interpret but just transmit in one way or another, embedded pointers
> should not do any harm.
>
> Imagine an IOCTL structure like this:
> struct MyIoctl
> {
> void* DataBuffer;
> ULONG BufferLengt;
> };
>
> If this structure is transmitted to the driver via buffered IO, one way
> for user mode to exploit the driver is not possible: changing the buffer
> while the driver is accessing it.
>
> As long as DataBuffer only contains arbitrary data that the driver has
> to transmit to/from some hardware (or in case of a FS to read or write
> it), then I don’t see much that can go wrong.
> ProbleForRead/ProbeForWrite, followed by either accessing it in a
> _try/_except block or building a MDL, should be perfectly fine.
> (Before doing it in real code, I would have a look at some sample that I
> know is doing it correctly :wink: )
> If the driver interprets the data in DataBuffer, however, then of
> course we might have yet another security problem.
>
>
> I have to admit that my sample is pretty simple, but it should
> illustrate my point.
>
> Now back to the original question: If DataBuffer is a 32bit pointer, how
> can a 64bit driver get access to the buffer?
>
> Best regards
>
> Rolf Schäuble
>
>

> However, for buffers that contain data that the driver does not

interpret but just transmit in one way or another, embedded pointers
should not do any harm.

You can, for instance, use the per-file state (FileObject->FsContext2) in the
driver to get rid of the pointers in IOCTL buffers. This will mean replacing 1
IOCTL call with 2 - first to set the state, second to transfer the data.

You can also use METHOD_OUT_DIRECT - which is “direct write with additional
buffered info”.

You can also use METHOD_IN_DIRECT - which is “direct read as a response to a
buffered request”.

And so on.

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

Don Burn wrote:

Please let me know your drivers that do this, I want to remove the security
holes from my
system. There is a heck of a lot of data validation you need to handle the
buffer pointer
and length combination correctly from all those nasty cases that can be
attacked from a
security point of view. The assumption that “don’t see much that can go
wrong” has
crashed more systems than I want to think about.

Well, no need for you to worry. All the drivers I have written so far
are only running on my own systems, and none of them uses anything but
buffered IO :wink:

However, I can understand your reaction. It’s always the things that you
don’t know that will go wrong. But let’s get back to my sample, because
I really would like to know where something could go wrong in your opinion:

  • The first thing I would do is to use ProbeForRead/ProbeForWrite (in a
    try/except block) with given DataBuffer and BufferLength. If this
    succeeds, then at least it’s clear that the buffer is entirely in the
    user mode part of the address space, and not partly or even completely
    in kernel mode address space.
  • Now we know that the buffer is really part of the app’s address space.
    Of course, as we all know, this does not guarantee that the buffer is
    actually accessible (which the application could change at arbitrary
    time with VirtualAlloc() and friends).
    This is easily handled by putting all the code in a try/except block.
  • Now the buffer can be (safely) accessed directly, or a MDL could be
    built to then lock down the pages.

There are a few points that I’ve ignored intentionally so far:

  • Is the data buffer length OK for the driver, i.e. can the driver
    handle this amount of data.
    However, this has nothing to do with the way the IOCTL gets down to the
    driver; it’s the same issue for buffered/direct/neither IO.
  • Alignment.
    This is also the same issue for all types of IOCTLs.

In case I have forgotten anything, please tell me, I’d like to learn.
To me, this sequence looks perfectly safe, and is what the DDK
documentation describes in the chapter ‘Using Neither Buffered Nor
Direct I/O’.

Best regards

Rolf Schäuble

> - Now the buffer can be (safely) accessed directly, or a MDL could be

built to then lock down the pages.

And what happens if the application, at this point, frees the block and
allocates a different one, where part of the mapping is in kernel space,
after you’ve probed it?


Mats

Maxim S. Shatskih wrote:

>However, for buffers that contain data that the driver does not
>interpret but just transmit in one way or another, embedded pointers
>should not do any harm.

You can, for instance, use the per-file state (FileObject->FsContext2) in the
driver to get rid of the pointers in IOCTL buffers. This will mean replacing 1
IOCTL call with 2 - first to set the state, second to transfer the data.
In some cases, doubling the amounts of IOCTLs can harm performance in a
non-acceptable way. Additionally, with multiple threads this two-step
operation might cause problems.

You can also use METHOD_OUT_DIRECT - which is “direct write with additional
buffered info”.

You can also use METHOD_IN_DIRECT - which is “direct read as a response to a
buffered request”.

And so on.

Thanks, but I already know all this. And I also know that my sample is
pretty stupid.
I’m really not so much interested in discussing the benefits and
problems of buffered/direct IO on one side and neither IO/embedded
pointers on the other side. That’s nothing new to me.

What I’m really interested in is: How to be nasty on a 64bit system with
a 32bit app :wink:

I don’t really need to know this for myself; I mostly want to know the
answer to this question just out of curiosity.
However, if I would be in the situation of the OP and get no answer to
the question, I would feel tempted to just try it out and if it works on
my systems, just assume that it will work on all systems. I’m sure you
agree that it would be much better if someone could say a definite ‘yes,
it works that way’ or ‘no, it does not work this way’, as it would safe
some people from getting bugchecks.
All those heated discussions here don’t help anyone, people will do it
the nasty way anyway; then why not tell them how to make the nasty
solution not crash?

  • Rolf Schäuble

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

xxxxx@3Dlabs.com wrote:

>- Now the buffer can be (safely) accessed directly, or a MDL could be
>built to then lock down the pages.

And what happens if the application, at this point, frees the block and
allocates a different one, where part of the mapping is in kernel space,
after you’ve probed it?


Mats

I don’t really understand.
Once ProbeForRead returns success, you know that the buffer is entirely
in the address range of the user mode app (0-2GB on non-PAE 32bit
systems; let’s ignore the rest for now). The application cannot change
its address space in any way.

The only thing the application can modify is the mapping of pages into
its address space. It could free the pages of the buffer, or change them
to disallow write access. But this is what the try/except block in the
driver is good for.

I don’t understand how the ‘where part of the mapping is in kernel
space, after you’ve probed it’ could happen.

  • Rolf Schäuble

Interesting but bit off discussion :-). Could someone pls come straight and answer the OP’s O question. AND ALREADY SOME OF THE REPLY TO THE POOR FOLK ROLF ARE AT BEST RANDOM SHOOTING !

-pro

> What I’m really interested in is: How to be nasty on a 64bit system with

a 32bit app :wink:

Try this article and the others referenced by it:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/kmarch/hh/kmarch/Other_6cff9ff8-fb41-4cb9-bbfd-b68e5fd17496.xml.asp

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

Maxim S. Shatskih wrote:

>What I’m really interested in is: How to be nasty on a 64bit system with
>a 32bit app :wink:

Try this article and the others referenced by it:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/kmarch/hh/kmarch/Other_6cff9ff8-fb41-4cb9-bbfd-b68e5fd17496.xml.asp

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

Thanks for this link. I’ve already read this a while ago, but just
skipped through it again right now.
This time, however, I think I found a ‘proof’ (well, ‘proof by example’)
that 32bit pointers can easily be reused:

In the chapter ‘Technique 2: Using IoIs32bitProcess’, when
IoIs32bitProcess(Irp) return true, the code copies over the 32bit
structure field by field into the 64bit version of the structure.
Especially interesting is this line:

LocalParam.Addr = params32->Addr

It just assignes the value of the 32bit pointer to a 64bit pointer.
I should have seen this the first time I’ve read this article.

Well, again thanks for this link.

  • Rolf Schäuble

First, embedded pointers are generally a bad idea and very few cases
actually require this type of design. I would strongly suggest
re-designing this IOCTL to accept a variable buffer, unless you are
expecting to parse rather large buffers (think disk IO or gigabit+
network IO here) using this IOCTL. Even then it might not be necessary.

Presuming you absolutely *must* do this, then look at how the
IOCTL_SCSI_PASS_THROUGH_DIRECT structures are defined. Basically,
define a special 32-bit version of your structure, but only for 64-bit
builds:

#if defined(_WIN64)
typedef struct _SCSI_PASS_THROUGH_DIRECT32 {
USHORT Length;
UCHAR ScsiStatus;
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
UCHAR CdbLength;
UCHAR SenseInfoLength;
UCHAR DataIn;
ULONG DataTransferLength;
ULONG TimeOutValue;
VOID * POINTER_32 DataBuffer;
ULONG SenseInfoOffset;
UCHAR Cdb[16];
}SCSI_PASS_THROUGH_DIRECT32, *PSCSI_PASS_THROUGH_DIRECT32;
#endif

In particular, note the “POINTER_32” markup on the embedded pointer.
Then, anyplace you process the IOCTL with an embedded pointer, you need
to determine if the application using the driver is 32-bit or 64-bit.
This can be done using the IoIs32bitProcess() API, with a trivial
example as follows:

#if defined (_WIN64)
if (IoIs32bitProcess(Irp)) {
DoTrace((TRACE_LEVEL_VERBOSE,
"32-bit IOCTL with embedded pointers "
“in 64-bit build”.));
}
#endif //defined (_WIN64)

As ‘cd’ mentioned, you cannot directly use this buffer address without
additional work. Generating the MDL is sufficient for hardware access
(but be careful about memory alignment requirements of the device), and
you still need to be sure that you’re in the original caller’s context
(which is only guaranteed by rules orthogonal to WDM – the storage
stack ensures this for storage IOCTLs, for example).

Good luck, as embedded pointers in IOCTLs is a very rocky road to
travel.

.

-----Original Message-----
From: cd [mailto:xxxxx@hotmail.com]
Sent: Monday, June 21, 2004 11:11 AM
Subject: Re: 32bit pointers for 64bit driver

You cannot use user buffer pointers in kernel space (32 bit or 64 bit).

I would assume that when you get a user buffer pointer, you could use
IoAllocateMdl to create an MDL using the 32bit pointer, lock the pages
using
MmProbeAndLockPages, and then use MmGetSystemAddressForMdlSafe to get a
kernel mode pointer. Make sure you probe & lock pages inside a
try/except
block .

“Al Shatilo” wrote in message news:xxxxx@ntdev…
> Hello All!
>
> We have a 32-bit application and 64-bit driver working together.
> In some IOCTLs we have embedded pointers to user mode buffers.
> How can we turn those 32bit pointers into 64bit pointers that our
driver
can use?
>
> Can we just do it this way:
> PTR32 p32 = ioctlStruct.pointer_to_buffer;
> PTR64 p64 = (PTR64)p32;
>
> or are other steps required?
>
>
>
> __________________________________
> Do you Yahoo!?
> Yahoo! Mail is new and improved - Check it out!
> http://promotions.yahoo.com/new_mail
>

Henry Gabryjelski wrote:

[…]

As ‘cd’ mentioned, you cannot directly use this buffer address without
additional work. Generating the MDL is sufficient for hardware access
(but be careful about memory alignment requirements of the device), and
you still need to be sure that you’re in the original caller’s context
(which is only guaranteed by rules orthogonal to WDM – the storage
stack ensures this for storage IOCTLs, for example).

Let’s assume that the handler for the IOCTL is running in the correct
process context, and that alignment and other such issues are taken care
of (or just don’t matter).
Under such conditions, is it a *must do* to build a MDL for the buffer,
or can the driver access it directly, assuming it does it correctly
(like probing, accessing it only in a try/except block etc.)?

Good luck, as embedded pointers in IOCTLs is a very rocky road to
travel.

.

  • Rolf Schäuble

Yes, in this case the pointer is valid. Of course, the pointer may not be properly aligned for 64-bit machines. The URL Maxim provided should highlight the important information on alignment issues, and marshalling the data into a 64-bit structure is highly recommended prior to use.

Since you’re also dealing with an embedded pointer, you will have to validate that the pointed-to-buffer is also properly aligned for all your accesses as well. This is in addition to the slew of all the other things you must do (such as allocating the MDL, mapping a system address, etc.).

One less commonly known vulnerability that should be considered is if the embedded pointer contains data that is validated in any way. Let’s consider the trivial example of a structure with a (ULONG) count of characters and variable-length set of UNICODE characters in it. Let’s also presume that your IOCTL only allows a maximum string length of 30k characters. You go ahead and probe/lock the buffer, then validate the LENGTH field (currently set to 12 characters). At this point, the application changes this field to -1. If your code is then copying the buffer based on this embedded buffer’s length field, you’re exposing a security hole.

To avoid most of these problems, only use embedded pointers for bulk data that is not referenced or trusted by the driver, or manually double-buffer(*) the data prior to verification/use.

Hth,
.

(*) If you’re buffering it anyways, what’s the point of using an embedded pointer? Better to redefine it to a variable-length buffer as part of the IOCTL and let the IO manager deal with this for you…

-----Original Message-----
From: Rolf Schaeuble [mailto:xxxxx@rschaeuble.de]
Sent: Tuesday, June 22, 2004 10:03 AM
Subject: Re: 32bit pointers for 64bit driver

Henry Gabryjelski wrote:

[…]

As ‘cd’ mentioned, you cannot directly use this buffer address without
additional work. Generating the MDL is sufficient for hardware access
(but be careful about memory alignment requirements of the device), and
you still need to be sure that you’re in the original caller’s context
(which is only guaranteed by rules orthogonal to WDM – the storage
stack ensures this for storage IOCTLs, for example).

Let’s assume that the handler for the IOCTL is running in the correct
process context, and that alignment and other such issues are taken care
of (or just don’t matter).
Under such conditions, is it a *must do* to build a MDL for the buffer,
or can the driver access it directly, assuming it does it correctly
(like probing, accessing it only in a try/except block etc.)?

Good luck, as embedded pointers in IOCTLs is a very rocky road to
travel.

.

  • Rolf Sch?uble