I’ve talked about MmMapLockedPagesSpecifyCache before, but this time I wanted to focus on the AccessMode parameter. If you specify an AccessMode of UserMode, the buffer returned will be a user virtual address. Thus, it will be visible to the user and will only be valid in the context of the process in which the call to MmMapLockedPagesSpecifyCache was made.
That’s all fine and good, but it brings up an interesting question when dealing with the x64 (as I’m wont to do, I’m ignoring the IA64 because I have no practical experience with it). When running Windows x64 editions, all kernel mode code is 64bit but user mode code can be either 32bit or 64bit. This great for app compat, but as a driver writer this can make your life more difficult.
Imagine that you have an IOCTL that has a data structure with an embedded HANDLE in it. HANDLEs are pointer precision, so if a 32bit application sends this IOCTL to you the buffer is going to have a different layout than if a 64bit application sends it to you. To fix this, you need to have multiple definitions of the IOCTL in your driver and use IoIs32bitProcess to determine which structure you should use.
But, what if part of the IOCTL processing involves mapping a buffer into the virtual address space of the application with MmMapLockedPagesSpecifyCache? Do you need to do anything special to make sure that the returned address is only 32bits wide if the caller is 32bit? The answer, thankfully, is no, you don’t need to do anything special. The Mm will make sure to return you an appropriately sized pointer for the current process’ user virtual address space.
Caveat emptor: It’s generally not considered best practice to map buffers into the user virtual address space. If it seems like a good idea to you and you can’t imagine what the problems with it might be, then you probably should think about another way to accomplish your task.