PIRP
MupBuildIoControlRequest(
  IN OUT PIRP Irp OPTIONAL,
  IN  PFILE_OBJECT FileObject OPTIONAL,
  IN  PVOID Context,
  IN  UCHAR MajorFunction,
  IN  ULONG IoControlCode,
  IN  PVOID MainBuffer,
  IN  ULONG InputBufferLength,
  IN  PVOID AuxiliaryBuffer OPTIONAL,
  IN  ULONG OutputBufferLength,
  IN  PIO_COMPLETION_ROUTINE CompletionRoutine
  );

Routine Description:

    This function builds an I/O request packet for a device or
    file system I/O control request.

Arguments:

    Irp - Supplies a pointer to an IRP.  If NULL, this routine allocates
        an IRP and returns its address.  Otherwise, it supplies the
        address of an IRP allocated by the caller.

    FileObject - Supplies a pointer the file object to which this
        request is directed.  This pointer is copied into the IRP, so
        that the called driver can find its file-based context.  NOTE
        THAT THIS IS NOT A REFERENCED POINTER.  The caller must ensure
        that the file object is not deleted while the I/O operation is
        in progress.  The server accomplishes this by incrementing a
        reference count in a local block to account for the I/O; the
        local block in turn references the file object.

    Context - Supplies a PVOID value that is passed to the completion
        routine.

    MajorFunction - The major function that we are calling.  Currently
        this most be one of IRP_MJ_FILE_SYSTEM_CONTROL or
        IRP_MJ_DEVICE_IO_CONTROL.

    IoControlCode - Supplies the control code for the operation.

    MainBuffer - Supplies the address of the main buffer.  This must
        be a system virtual address, and the buffer must be locked in
        memory.  If ControlCode specifies a method 0 request, the actual
        length of the buffer must be the greater of InputBufferLength
        and OutputBufferLength.

    InputBufferLength - Supplies the length of the input buffer.

    AuxiliaryBuffer - Supplies the address of the auxiliary buffer.  If the
        control code method is 0, this is a buffered I/O buffer, but the
        data returned by the called driver in the system buffer is not
        automatically copied into the auxiliary buffer.  Instead, the
        auxiliary data ends up in MainBuffer.  If the caller wishes the
        data to be in AuxiliaryBuffer, it must copy the data at some point
        after the completion routine runs.

        If the control code method is 1 or 2, this parameter is ignored;
        instead, the Mdl parameter is used to obtain the starting
        virtual address of the buffer.

    CompletionRoutine - The IO completion routine.

Return Value:

    PIRP - Returns a pointer to the constructed IRP.  If the Irp
        parameter was not NULL on input, the function return value will
        be the same value (so it is safe to discard the return value in
        this case).  It is the responsibility of the calling program to
        deallocate the IRP after the I/O request is complete.