Programming 版 (精华区)

发信人: zpw (zhao), 信区: Programming
标  题: Using IOXTL METHOD_NEITHER
发信站: 紫 丁 香 (Wed Jul 29 20:59:37 1998), 转信

Using IOCTL METHOD_NEITHER

If you read our earlier tip on METHOD_IN/OUT_DIRECT, you may have been left 
wondering about the details of the other IOCTL methods, METHOD_BUFFERED, and 
METHOD_NEITHER. This tip explores the latter, lesser known of the two, 
METHOD_NEITHER.

If an IOCTL code passed to DeviceIoControl is defined using METHOD_NEITHER, the
operating system performs no address translation or validation of pointers 
passed in parameters InputBuffer and OutputBuffer. Because there is relatively
less work for the system to do, it can deliver an IRP that uses METHOD_NEITHER
to a driver faster than it can IRPs that use the other two IOCTL methods. 
However, the burden is now on the driver to ensure that the pointers passed to
it are valid. In addition, the driver can use the raw pointers only in the 
context of the calling process.


As shown in the diagram, the pointer passed as parameter InputBuffer appears in
field 

IoGetCurrentIrpStackLocation(pIrp)->Parameters.DeviceIoControl.Type3InputBuffer.

The pointer passed as parameter OutputBuffer appears in  pIrp-> UserBuffer. 
Because the operating system has not validated the pointers passed to a driver
in a METHOD_NEITHER IRP, it is crucial to guard against exceptions that could 
result from accessing these pointers. A driver can easily trap an exception 
that results from dereferencing a bad pointer by bracketing access to the 
pointer in a _try/_except block. Here is some Driver::Works code that 
illustrates the basic idea:

NTSTATUS MyDevice::DeviceControl(KIrp I)
{

        switch (I.IoctlCode())
        {
        case IOCTL_NEITHER_OPERATION:
                PINPUT_DATA pInput = PINPUT_DATA(I.IoctlType3InputBuffer());
                PULONG pOutput = I.UserBuffer();

                _try
                {
                        NTSTATUS status=Process(pInput, pOutput);       
                        return I.Complete(status);
                }
                _except ( EXCEPTION_EXECUTE_HANDLER )
                {
                        I.Information()=0;
                        return I.Complete(STATUS_ACCESS_DENIED);
                }
        // etc.
        }
}
The other important thing to remember about pointers in a METHOD_NEITHER IRP is
that they may be used only in the context of the calling process. If your 
driver serializes requests through StartIo, or ever needs to access the buffers
from an arbitrary thread context or at IRQL > PASSIVE_LEVEL, then your driver 
must lock down the buffers and map them to system space. The system services 
you'll need are MmCreateMdl, MmProbeAndLockPages, and MmGetSystemAddressForMdl.

In summary, METHOD_NEITHER can be useful for certain kinds of requests.   
The precaution of structured exception handling (_try/_except) is required when
ever accessing pointers that have not been validated by the system. If the 
driver can process the request quickly and without synchronization, then 
METHOD_NEITHER provides an easy and efficient mechanism. However, most of the 
time it is better to take advantage of the operating system's facilities for 
buffer management, using either METHOD_IN/OUT_DIRECT, or METHOD_BUFFERED.

--
※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: yaoyu.hit.edu.cn]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:3.365毫秒