158 lines
5.4 KiB
C++
158 lines
5.4 KiB
C++
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
FsCtlBuf.h
|
||
|
||
Abstract:
|
||
|
||
This module defines routines that get the buffers for the various types of ioctl/fsctls. It is essntially
|
||
just the reverse of the IopXXXControlFile routine in io\internal.c, the appropriate parts of which are
|
||
reproduced here.
|
||
|
||
Author:
|
||
|
||
Joe Linn [JoeLinn] 4-aug-1994
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#ifndef _fsctlbuf_
|
||
#define _fsctlbuf_
|
||
|
||
// the presentation here is in three pieces: the macros for METHODBUFFERED, METHODDIRECT, AND METHODNEITHER.
|
||
// it's set up this way so that you can find out what you've got just by reading this and not looking thru
|
||
// IO system....
|
||
|
||
/* here is the code for case 0
|
||
case 0:
|
||
|
||
//
|
||
// For this case, allocate a buffer that is large enough to contain
|
||
// both the input and the output buffers. Copy the input buffer to
|
||
// the allocated buffer and set the appropriate IRP fields.
|
||
//
|
||
|
||
try {
|
||
|
||
if (InputBufferLength || OutputBufferLength) {
|
||
irp->AssociatedIrp.SystemBuffer =
|
||
RxAllocatePool( poolType,
|
||
(InputBufferLength > OutputBufferLength) ? InputBufferLength : OutputBufferLength );
|
||
|
||
if (ARGUMENT_PRESENT( InputBuffer )) {
|
||
RtlCopyMemory( irp->AssociatedIrp.SystemBuffer,
|
||
InputBuffer,
|
||
InputBufferLength );
|
||
}
|
||
irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
|
||
irp->UserBuffer = OutputBuffer;
|
||
if (ARGUMENT_PRESENT( OutputBuffer )) {
|
||
irp->Flags |= IRP_INPUT_OPERATION;
|
||
}
|
||
} else {
|
||
irp->Flags = 0;
|
||
irp->UserBuffer = (PVOID) NULL;
|
||
}
|
||
|
||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||
<<<elided>>>
|
||
}
|
||
|
||
break;
|
||
|
||
So, the bottom line is that irp->AssociatedIrp.SystemBuffer is a buffer of length (I-length+O-length) and
|
||
is preloaded with the input. Even though the original outputbuffer is passed thru in irp->UserBuffer, it is not to be used
|
||
in the FS; rather the FS writes its answer into the same buffer. we get the
|
||
following macros:
|
||
|
||
*/
|
||
#define METHODBUFFERED_SharedBuffer(IRP) (IRP)->AssociatedIrp.SystemBuffer
|
||
|
||
|
||
/* for 1 and 2
|
||
|
||
case 1:
|
||
case 2:
|
||
|
||
//
|
||
// For these two cases, allocate a buffer that is large enough to
|
||
// contain the input buffer, if any, and copy the information to
|
||
// the allocated buffer. Then build an MDL for either read or write
|
||
// access, depending on the method, for the output buffer. Note
|
||
// that the buffer length parameters have been jammed to zero for
|
||
// users if the buffer parameter was not passed. (Kernel callers
|
||
// should be calling the service correctly in the first place.)
|
||
//
|
||
// Note also that it doesn't make a whole lot of sense to specify
|
||
// either method #1 or #2 if the IOCTL does not require the caller
|
||
// to specify an output buffer.
|
||
//
|
||
|
||
try {
|
||
|
||
if (InputBufferLength && ARGUMENT_PRESENT( InputBuffer )) {
|
||
irp->AssociatedIrp.SystemBuffer =
|
||
RxAllocatePool( poolType, InputBufferLength );
|
||
RtlCopyMemory( irp->AssociatedIrp.SystemBuffer,
|
||
InputBuffer,
|
||
InputBufferLength );
|
||
irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
|
||
} else {
|
||
irp->Flags = 0;
|
||
}
|
||
|
||
if (OutputBufferLength != 0) {
|
||
irp->MdlAddress = IoAllocateMdl( OutputBuffer,
|
||
OutputBufferLength,
|
||
FALSE,
|
||
TRUE,
|
||
irp );
|
||
if (irp->MdlAddress == NULL) {
|
||
ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
|
||
}
|
||
MmProbeAndLockPages( irp->MdlAddress,
|
||
requestorMode,
|
||
(LOCK_OPERATION) ((method == 1) ? IoReadAccess : IoWriteAccess) );
|
||
}
|
||
|
||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||
<<<ELIDED>>>
|
||
}
|
||
|
||
break;
|
||
|
||
So the deal is that the input buffer has been copied in as in case 0 but what we have is an MDL for
|
||
the output buffer. this leads to the following
|
||
*/
|
||
|
||
|
||
#define METHODDIRECT_BufferedInputBuffer(IRP) ((IRP)->AssociatedIrp.SystemBuffer)
|
||
#define METHODDIRECT_DirectBuffer(IRP) (((IRP)->MdlAddress) \
|
||
? MmGetSystemAddressForMdlSafe((IRP)->MdlAddress,NormalPagePriority):NULL)
|
||
|
||
/* and finally
|
||
case 3:
|
||
|
||
//
|
||
// For this case, do nothing. Everything is up to the driver.
|
||
// Simply give the driver a copy of the caller's parameters and
|
||
// let the driver do everything itself.
|
||
//
|
||
|
||
irp->UserBuffer = OutputBuffer;
|
||
irpSp->Parameters.DeviceIoControl.Type3InputBuffer = InputBuffer;
|
||
}
|
||
|
||
So we can get 'em.....but we don't really know how they're gonna be used. Nevertheless.......
|
||
*/
|
||
|
||
#define METHODNEITHER_OriginalInputBuffer(IRPSP) ((IRPSP)->Parameters.DeviceIoControl.Type3InputBuffer)
|
||
#define METHODNEITHER_OriginalOutputBuffer(IRP) ((IRP)->UserBuffer)
|
||
|
||
|
||
#endif // _fsctlbuf_
|
||
|