Note that the call to VirtualLock here is unnecessary and requires UM privileges that may not be present (seLockMemory). It is good practice of course to do this, but it is not strictly necessary as in KM all buffers from UM must be probed and locked as a matter of course to prevent security issues
Note also that signaling an event that a UM thread has been waiting on will require interaction with the scheduler, a KM / UM transition and possibly a context switch. This overheat exactly parallels the most costly parts of an IOCTL plus an interaction with the scheduler which may not be required for an IOCTL. It is of course possible to avoid these overheads by using only interlocked operations in the shared memory region, but that would mean developing your own version of an CRITICAL_SECTION that can be shared between UM & KM (an inherent security issue) or using a spin wait in UM ? nether is an attractive option IMHO.
I have said many times on this form, that a correct implementation of a shared memory interface with a UM app generally is much more complex and performs no better than the use of IOCTLs. Clearly it is possible to do better under specific circumstances where you can make assumptions that the MSFT engineers cannot, but do you really think you can outguess the 1,000+ man years that MSFT have put into the NT kernel? ( I have no figures on this, but it seems a reasonable number)
Sent from Mailhttps: for Windows 10
From: Jamey Kirbymailto:xxxxx
Sent: June 4, 2017 12:49 PM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: Re: [ntdev] ZwMapViewOfSection’s BaseAddress is unaccessable
davg556:
1) Set up an IOCTL in your driver.
2) In user mode, allocate your buffer with VirtualAlloc(…, COMMIT | RESERVE);
3) Lock the buffer with VirtualLock()
4) Create your events
5) Call that IOCTL with your buffer, and your events in a data structure.
6) Reference the event handles with ObReferenceObjectByHandle() so that you can use kernel primitives to access the events. You could not do this and use functions like ZwSetEvent() rather than KeSetEvent(), but I prefer to use the native objects when in kernel mode, so I do the reference. It gives you more flexibility.
7) In the IOCTL, you are running in the process context of the UM app that called you, so now create a thread with PsCreateSystemThread(), but for the process parameter, instead of passing NULL for the system process, pass ZwCurrentProcess(). This will cause the thread to be created in your UM processes context. If you run procexp.exe, you’ll see your thread running as a thread in your process (but owned by your driver). Now, when your thread is running, it will have access to everything in your processes space.
When your process terminates, your thread will NOT terminate, so you have to handle that. One event that I pass down to the driver is a terminate event. If the user-mode apps sets this event, it signals the thread to terminate, and do any app specific cleanup. I pass two events (terminate_start_event, and terminate_stop_event). When my application wants to terminate, I set this start event, and then wait for the complete event in WaifForSingleObjet(). This synchronized the threads termination so that the application does not terminate before the thread terminates. The driver cleans up, and the sets the terminate complete event.
Abnormal termination is handled by sending as another parameter to the IOCTL, the main processes thread (the thread that is running under main(), WinMain(), or ServiceMain()). This is a fail safe in the event that the application terminates abnormally. This thread is also waited on in the driver. If it is set, do your cleanup and terminate the thread.
That handles termination. Now for request processing. I send in a start_request event, and a complete_request event. When the driver needs work from UM, it fills in the buffer, and then sets the start_event, and then waits on the complete event. UM gets the start event, processed the request in the buffer, and when done, sets the complete event.
You need to wrap access to your UM objects and buffers in a try except block; safety check for bad hombres.
My driver is quite complex, and I pass lots of things to the driver. What I outlined is a simple case. I did mine the way I did more as an exercise than for practicality. My goal was to reduce the IOCTLs to the driver to one.
It was a little tricky to get everything working smoothly, but it is now rock-solid with excellent data transfer speeds.
I wrote this post in a bit of a rush, so I apologize in advance for my chicken scratch.
– Jamey
On Sun, Jun 4, 2017 at 12:01 PM Jamey Kirby > wrote:
Sure. I’ll do it shortly when I get back to my desk
On Sun, Jun 4, 2017, 7:31 AM > wrote:
@Jamey Kirby can you post some guidelines?
—
NTDEV is sponsored by OSR
Visit the list online at: http:
MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at http:
To unsubscribe, visit the List Server section of OSR Online at http:
— NTDEV is sponsored by OSR Visit the list online at: MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers! Details at To unsubscribe, visit the List Server section of OSR Online at</http:></http:></http:></mailto:xxxxx></mailto:xxxxx></https:>