/*++ 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) { <<>> } 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) { <<>> } 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_