Everhart,Glenn
From:	Sethuraman, Ramesh [sethur@xgate.ColumbiaSC.NCR.COM]
Sent:	Wednesday, March 18, 1998 11:22 AM
To:	'NT Device Driver'
Subject:	[ntdev]- Sharing memory between Kernel mode and user mode..
Some time before, there were discussions about the above topic.
I got this stuff from NT internals site. For those of you who may not
have seen this before..
Thanks..
Ramesh Sethuraman

How To Share Memory Between Kernel
Mode And User Mode

 The recommended way to share memory between user mode and kernel mode
is to take advantage of the memory locking and address translation
mechanisms that the system uses for passing requests to drivers. An
application simply passes the
 address and size of the buffer to be shared as a parameter to
DeviceIoControl, and the system automatically locks it into memory and
provides a system address for the driver. There are just a few things to
remember when setting up this kind of
mechanism.

 First of all, the IOCTL code that the application uses when passing the
buffer must be constructed using the correct buffer method, namely
METHOD_IN_DIRECT. For example,

 #define IOCTL_MYDRIVER_SHARE_BUFFER \
 CTL_CODE(FILE_DEVICE_UNKNOWN, 1, METHOD_IN_DIRECT,
 FILE_ANY_ACCESS)

 Second, the call to DeviceIoControl must use asynchronous completion,
which is also known as "overlapped I/O". Here is some code that shows
how that is done:

 HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
 OVERLAPPED ov;
 memset (&ov, 0, sizeof(OVERLAPPED));
 ov.hEvent = hEvent;
 DeviceIoControl(
         hDevice,
         IOCTL_MYDRIVER_SHARE_BUFFER,
         NULL,
         0,
         BufferToBeShared,
         SizeOfBufferToBeShared,
         &nBytesReturned,
         &ov
         );

 In the driver, the handler for IRP_MJ_DEVICE_CONTROL obtains the system
address of the buffer via the MDL in the IRP, and then pends the
request. When the buffer is no longer needed, the application calls
DeviceIoControl again, this time with code
IOCTL_MYDRIVER_DONE_USING_SHARE_BUFFER . The driver then completes the
original IRP.

 NTSTATUS MyDevice::DriverControl(Kirp I)
 {
     switch (I.IoctlCode())
     {
         case IOCTL_MYDRIVER_SHARE_BUFFER:
             KMemory M(I.Mdl());
             m_SharedBuffer = M.MapToSystemSpace();
             m_SharedBufferIrp = I;
             return STATUS_PENDING;

         case IOCTL_MYDRIVER_DONE_USING_SHARE_BUFFER:
             return m_SharedBufferIrp.Complete(STATUS_SUCCESS);
         . . .
         }
 . . .
> }
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[ To unsubscribe, send email to ntdev-request@atria.com with body
UNSUBSCRIBE (the subject is ignored). ]