/* Editor Settings: expandtabs and use 4 spaces for indentation
 * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: *
 * -*- mode: c, c-basic-offset: 4 -*- */

/*
 * Copyright (c) Likewise Software.  All rights Reserved.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the license, or (at
 * your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
 * General Public License for more details.  You should have received a copy
 * of the GNU Lesser General Public License along with this program.  If
 * not, see <http://www.gnu.org/licenses/>.
 *
 * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING
 * TERMS AS WELL.  IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT
 * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE
 * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU
 * LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE.  IF YOU
 * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING
 * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT
 * license@likewise.com
 */

/*
 * Copyright (C) Likewise Software. All rights reserved.
 *
 * Module Name:
 *
 *        ntfileapi.h
 *
 * Abstract:
 *
 *        NT File API
 *
 * Authors: Danilo Almeida (dalmeida@likewisesoftware.com)
 */

#ifndef __NT_FILE_API_H__
#define __NT_FILE_API_H__

/**
 * @file lwio/ntfileapi.h
 * @brief Likewise I/O Client File API
 */

#include <lwio/io-types.h>
#include <lwio/iortl.h>

LW_BEGIN_EXTERN_C

/**
 * @defgroup ntfileapi File API
 * @ingroup client
 * @brief Client file API with NT semantics
 *
 * @code
 * #include <lwio/lwio.h>
 * // Link with -llwioclient
 * @endcode
 *
 * The @ref ioapi "iomgr file API" is only available to drivers loaded by lwio.
 * This API exposes it in a way that is accessible to any process that links
 * with @a liblwioclient.
 */

/*@{*/

//
// The operations below are in categories:
//
// - Core I/O
// - Additional
// - Namespace
// - Advanced
//

//
// Core I/O Operations
//

NTSTATUS
LwNtCreateNamedPipeFile(
    OUT PIO_FILE_HANDLE FileHandle,
    IN OUT OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    OUT PIO_STATUS_BLOCK IoStatusBlock,
    IN PIO_FILE_NAME FileName,
    IN OPTIONAL PVOID SecurityDescriptor, // TBD
    IN OPTIONAL PVOID SecurityQualityOfService, // TBD
    IN ACCESS_MASK DesiredAccess,
    IN FILE_SHARE_FLAGS ShareAccess,
    IN FILE_CREATE_DISPOSITION CreateDisposition,
    IN FILE_CREATE_OPTIONS CreateOptions,
    IN FILE_PIPE_TYPE_MASK NamedPipeType,
    IN FILE_PIPE_READ_MODE_MASK ReadMode,
    IN FILE_PIPE_COMPLETION_MODE_MASK CompletionMode,
    IN ULONG MaximumInstances,
    IN ULONG InboundQuota,
    IN ULONG OutboundQuota,
    IN OPTIONAL PLONG64 DefaultTimeout
    );

/**
 * @brief Create or open file
 *
 * Creates or opens a file.  This is comparable in behavior to
 * #IoCreateFile(), but does not allow a security context to
 * be passed directly, as this ability is restricted to drivers
 * running within lwio.  The credential handle parameter does
 * permit a subset of the functionality to be used, however:
 *
 * - To pass credentials to use with a remote server
 *   (e.g. #LwIoCreateKrb5CredsW), such as through the @a rdr
 *   driver.
 * - To impersonate a user (#LwIoCreateImpersonationCreds) when
 *   the caller is a privileged (root) process.
 *
 * If no credentials are provided, the default for the thread will
 * be used (see #LwIoSetThreadCreds).
 *
 * @param[out]    FileHandle               Set to the created file handle on completion.
 * @param[in,out] AsyncControlBlock        Optional async control block.  If specified,
 *                                         @a LW_STATUS_PENDING may be returned and
 *                                         @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock            Filled with result information on completion.
 * @param[in]     FileName                 The file path to create or open.
 * @param[in]     SecurityDescriptor       An optional initial security descriptor.  This is
 *                                         only effective if the file is created or superseded.
 * @param[in]     SecurityQualityOfService Currently unused.  Must be @a NULL.
 * @param[in]     DesiredAccess            A mask of desired access bits.
 * @param[in]     AllocationSize           An optional allocation size, or @a 0.  This is only effective
 *                                         if the file is created or superseded.
 * @param[in]     FileAttributes           A mask of attributes for the created or opened file.
 * @param[in]     ShareAccess              A mask of share access flags.
 * @param[in]     CreateDisposition        The type of create to perform.
 * @param[in]     CreateOptions            A mask of additional create options.
 * @param[in]     EaBuffer                 An optional @a PFILE_FULL_EA_INFORMATION specifying initial EAs.
 *                                         This is only effective if the file is created or superseded.
 * @param[in]     EaLength                 The length of @a EaBuffer, or 0.
 * @param[in]     EcpList                  An optional list of extended create parameters.
 * @param[in]     pCreds                   A credential handle.
 *
 * @retval LW_STATUS_SUCCESS               Success.
 * @retval LW_STATUS_PENDING               The operation will be completed asynchronously by
 *                                         invoking @a AsyncControlBlock->Callback.  The final result
 *                                         status can be obtained from @a IoStatusBlock->Status.
 * @retval LW_STATUS_OBJECT_PATH_NOT_FOUND A leading path element in @a FileName did
 *                                         not exist.
 * @retval LW_STATUS_OBJECT_NAME_NOT_FOUND The specified file did not exist.
 * @retval LW_STATUS_ACCESS_DENIED         The calling user was denied one or more of the desired
 *                                         access bits.  This will not be returned if @a DesiredAccess
 *                                         contained only MAXIMUM_ALLOWED.
 * @retval LW_STATUS_SHARING_VIOLATION     The given @a ShareAccess flags or those of another
 *                                         open handle did not permit concurrent access to the
 *                                         file with the requested access mask.
 * @retval LW_STATUS_NOT_A_DIRECTORY       @a CreateOptions contained #FILE_DIRECTORY_FILE but
 *                                         the specified path existed and was not a directory.
 * @retval LW_STATUS_FILE_IS_A_DIRECTORY   @a CreateOptions contained #FILE_NON_DIRECTORY_FILE but
 *                                         the specified path existed and was a directory.
 * @retval LW_STATUS_DELETE_PENDING        The file could not be opened because it is pending deletion.
 * @retval ...                             Error.
 */
LW_NTSTATUS
LwNtCreateFile(
    LW_OUT PIO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_IN PIO_FILE_NAME FileName,
    LW_IN LW_OPTIONAL PSECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor,
    LW_IN LW_OPTIONAL LW_PVOID SecurityQualityOfService, // TBD
    LW_IN ACCESS_MASK DesiredAccess,
    LW_IN LW_OPTIONAL LONG64 AllocationSize,
    LW_IN FILE_ATTRIBUTES FileAttributes,
    LW_IN FILE_SHARE_FLAGS ShareAccess,
    LW_IN FILE_CREATE_DISPOSITION CreateDisposition,
    LW_IN FILE_CREATE_OPTIONS CreateOptions,
    LW_IN LW_OPTIONAL LW_PVOID EaBuffer, // PFILE_FULL_EA_INFORMATION
    LW_IN LW_ULONG EaLength,
    LW_IN LW_OPTIONAL PIO_ECP_LIST EcpList,
    LW_IN LW_OPTIONAL LW_PIO_CREDS pCreds
    );

/**
 * @brief Close file handle
 *
 * Closes a file handle.  Unlike #IoCloseFile(), this call
 * may file due to issues communicating with the lwio service.
 *
 * @param[in,out] FileHandle  The file handle.
 *
 * @retval LW_STATUS_SUCCESS  Success.
 * @retval ...                Error.  The file handle was freed, but the close operation
 *                            itself may not have been processed.
 */
LW_NTSTATUS
LwNtCloseFile(
    LW_IN IO_FILE_HANDLE FileHandle
    );

/**
 * @brief Close file handle asynchronously
 *
 * Closes a file handle with optional asynchronous behavior.
 * Unlike #IoAsyncCloseFile(), this call may fail due to issues
 * communicating with the lwio service.
 *
 * @param[in,out] FileHandle        The file handle.
 * @param[in,out] AsyncControlBlock Optional async control block.  If specified,
 *                                  @a LW_STATUS_PENDING may be returned and
 *                                  @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock     Filled with result information on completion.
 *
 * @retval LW_STATUS_SUCCESS  Success.
 * @retval LW_STATUS_PENDING  The operation will be completed asynchronously by
 *                            invoking @a AsyncControlBlock->Callback.  The final result
 *                            status can be obtained from @a IoStatusBlock->Status.
 * @retval ...                Error.  The file handle was freed, but the close operation
 *                            itself may not have been processed.
 */
LW_NTSTATUS
LwNtAsyncCloseFile(
    LW_IN IO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock
    );

/**
 * @brief Read from file
 *
 * Reads from the specified file handle.  Analogous to #IoReadFile(), but
 * lacks the @a IoFlags parameter, which is restricted to drivers running
 * within lwio.
 *
 * @param[in]     FileHandle        The handle to read from.
 * @param[in,out] AsyncControlBlock Optional async control block. If specified,
 *                                  @a LW_STATUS_PENDING may be returned and
 *                                  @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock     Filled with result information on completion.
 * @param[out]    Buffer            The buffer where the read data should be placed.
 * @param[in]     Length            The number of bytes to read.
 * @param[in]     ByteOffset        An optional byte offset into file from which to read.
 *                                  If not specified, the current file handle position is used.
 * @param[in]     Key               Currently unused.  Must be @a NULL.
 *
 * @retval LW_STATUS_SUCESS             Success.
 * @retval LW_STATUS_PENDING            The operation will be completed asynchronously by
 *                                      invoking @a AsyncControlBlock->Callback.  The final result
 *                                      status can be obtained from @a IoStatusBlock->Status.
 * @retval LW_STATUS_END_OF_FILE        No data was read because the end of the file was reached.
 * @retval LW_STATUS_FILE_LOCK_CONFLICT A conflicting lock prevented the read.
 * @retval LW_STATUS_ACCESS_DENIED      The handle was not opened with #FILE_READ_DATA, or if
 *                                      #IO_FLAG_PAGING_IO was specified, #FILE_EXECUTE.
 * @retval ...                          Error.
 */
LW_NTSTATUS
LwNtReadFile(
    LW_IN IO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_OUT LW_PVOID Buffer,
    LW_IN LW_ULONG Length,
    LW_IN LW_OPTIONAL LW_PULONG64 ByteOffset,
    LW_IN LW_OPTIONAL LW_PULONG Key
    );

/**
 * @brief Write to file
 *
 * Writes to the specified file handle. Analogous to #IoWriteFile(), but
 * lacks the @a IoFlags parameter, which is restricted to drivers running
 * within lwio.
 *
 * @param[in]     FileHandle The handle to read from.
 * @param[in,out] AsyncControlBlock Optional async control block. If specified,
 *                                  @a LW_STATUS_PENDING may be returned and
 *                                  @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock     Filled with result information on completion.
 * @param[out]    Buffer            The buffer containing data to write.
 * @param[in]     Length            The number of bytes to write.
 * @param[in]     ByteOffset        An optional byte offset into file to which to write.
 *                                  If not specified, the current file handle position is used.
 * @param[in]     Key               Currently unused.  Must be @a NULL.
 *
 * @retval LW_STATUS_SUCCESS            Success.
 * @retval LW_STATUS_PENDING            The operation will be completed asynchronously by
 *                                      invoking @a AsyncControlBlock->Callback.  The final result
 *                                      status can be obtained from @a IoStatusBlock->Status.
 * @retval LW_STATUS_DISK_FULL          There was insufficient space on the device containing the file.
 * @retval LW_STATUS_FILE_LOCK_CONFLICT A conflicting lock prevented the write.
 * @retval LW_STATUS_ACCESS_DENIED      The handle was not opened with #FILE_WRITE_DATA access.
 * @retval ...                          Error.
 */
LW_NTSTATUS
LwNtWriteFile(
    LW_IN IO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_IN LW_PVOID Buffer,
    LW_IN LW_ULONG Length,
    LW_IN LW_OPTIONAL LW_PULONG64 ByteOffset,
    LW_IN LW_OPTIONAL LW_PULONG Key
    );

/**
 * @brief Send driver-specific control code
 *
 * Sends a control code directly to a driver.  Analogous to #IoDeviceIoControlFile().
 *
 * @param[in]     FileHandle         A handle to the driver.  This should generally
 *                                   be obtained by using #LwNtCreateFile() on "/<device>".
 * @param[in,out] AsyncControlBlock  Optional async control block. If specified,
 *                                   @a LW_STATUS_PENDING may be returned and
 *                                   @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock      Filled with result information on completion.
 * @param[in]     IoControlCode      The control code to send.
 * @param[out]    InputBuffer        A buffer containing data to pass to the device.
 * @param[in]     InputBufferLength  The number of bytes to pass to the device.
 * @param[out]    OutputBuffer       A buffer into which output data will be written by the device.
 * @param[in]     OutputBufferLength The length of @a OutputBuffer.
 *
 * @retval LW_STATUS_SUCCESS Success.
 * @retval LW_STATUS_PENDING The operation will be completed asynchronously by
 *                           invoking @a AsyncControlBlock->Callback.  The final result
 *                           status can be obtained from @a IoStatusBlock->Status.
 * @retval ...               Error.
 */
LW_NTSTATUS 
LwNtDeviceIoControlFile(
    LW_IN IO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_IN LW_ULONG IoControlCode,
    LW_IN LW_PVOID InputBuffer,
    LW_IN LW_ULONG InputBufferLength,
    LW_OUT LW_PVOID OutputBuffer,
    LW_IN LW_ULONG OutputBufferLength
    );

/**
 * @brief Send filesystem control code
 *
 * Sends a control code to perform an operation on a file, directory,
 * or underlying filesystem.  Analogous to #IoFsControlFile().
 *
 * @param[in]     FileHandle         A handle to the driver.  This should generally
 *                                   be obtained by using #IoCreateFile() on "/<device>".
 * @param[in,out] AsyncControlBlock  Optional async control block. If specified,
 *                                   @a LW_STATUS_PENDING may be returned and
 *                                   @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock      Filled with result information on completion.
 * @param[in]     FsControlCode      The control code to send.
 * @param[out]    InputBuffer        A buffer containing data to pass to the device.
 * @param[in]     InputBufferLength  The number of bytes to pass to the device.
 * @param[out]    OutputBuffer       A buffer into which output data will be written by the device.
 * @param[in]     OutputBufferLength The length of @a OutputBuffer.
 *
 * @retval LW_STATUS_SUCCESS Success.
 * @retval LW_STATUS_PENDING The operation will be completed asynchronously by
 *                           invoking @a AsyncControlBlock->Callback.  The final result
 *                           status can be obtained from @a IoStatusBlock->Status.
 * @retval ...               Error.
 */
LW_NTSTATUS
LwNtFsControlFile(
    LW_IN IO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_IN LW_ULONG FsControlCode,
    LW_IN LW_PVOID InputBuffer,
    LW_IN LW_ULONG InputBufferLength,
    LW_OUT LW_PVOID OutputBuffer,
    LW_IN LW_ULONG OutputBufferLength
    );

/**
 * @brief Flush data to stable storage.
 *
 * Flushes all modifications for the given file handle to permanent storage.
 * Analogous to #IoFlushBuffersFile().
 *
 * @param[in]     FileHandle         The file handle.
 * @param[in,out] AsyncControlBlock  Optional async control block. If specified,
 *                                   @a LW_STATUS_PENDING may be returned and
 *                                   @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock      Filled with result information on completion.
 *
 * @retval LW_STATUS_SUCCESS Success.
 * @retval LW_STATUS_PENDING The operation will be completed asynchronously by
 *                           invoking @a AsyncControlBlock->Callback.  The final result
 *                           status can be obtained from @a IoStatusBlock->Status.
 * @retval ...               Error.
 */
LW_NTSTATUS
LwNtFlushBuffersFile(
    LW_IN IO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock
    );

/**
 * @brief Query file information
 *
 * Queries for information about a file.  Analogous to #IoQueryInformationFile().
 *
 * @param[in]     FileHandle           The file handle.
 * @param[in,out] AsyncControlBlock    Optional async control block. If specified,
 *                                     @a LW_STATUS_PENDING may be returned and
 *                                     @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock        Filled with result information on completion.
 * @param[out]    FileInformation      A buffer which is filled with the requested
 *                                     information.
 * @param[in]     Length               The size of @a FileInformation in bytes.
 * @param[in]     FileInformationClass The type of file information to query.
 *
 * @retval LW_STATUS_SUCCESS            Success.
 * @retval LW_STATUS_PENDING            The operation will be completed asynchronously by
 *                                      invoking @a AsyncControlBlock->Callback.  The final result
 *                                      status can be obtained from @a IoStatusBlock->Status.
 * @retval LW_STATUS_BUFFER_TOO_SMALL   The passed buffer was too small to contain the
 *                                      requested information.
 * @retval LW_STATUS_BUFFER_OVERFLOW    The passed buffer was large enough to contain the fixed
 *                                      portion of the requested info structure, but not the
 *                                      variable-sized trailing portion.
 * @retval LW_STATUS_INVALID_INFO_CLASS The specified information class was invalid.
 * @retval ...                          Error.
 */
LW_NTSTATUS 
LwNtQueryInformationFile(
    LW_IN IO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_OUT LW_PVOID FileInformation,
    LW_IN LW_ULONG Length,
    LW_IN FILE_INFORMATION_CLASS FileInformationClass
    );

/**
 * @brief Set file information
 *
 * Sets information about a file.  Analogous to #IoSetInformationFile().
 *
 * @param[in]     FileHandle           The file handle.
 * @param[in,out] AsyncControlBlock    Optional async control block. If specified,
 *                                     @a LW_STATUS_PENDING may be returned and
 *                                     @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock        Filled with result information on completion.
 * @param[in]     FileInformation      A buffer which contains the information to set.
 * @param[in]     Length               The size of @a FileInformation in bytes.
 * @param[in]     FileInformationClass The type of file information to query.
 *
 * @retval LW_STATUS_SUCCESS              Success.
 * @retval LW_STATUS_PENDING              The operation will be completed asynchronously by
 *                                        invoking @a AsyncControlBlock->Callback.  The final result
 *                                        status can be obtained from @a IoStatusBlock->Status.
 * @retval LW_STATUS_INFO_LENGTH_MISMATCH The passed buffer had the wrong length for the specified
 *                                        information class.
 * @retval LW_STATUS_INVALID_INFO_CLASS   The specified information class was invalid.
 * @retval ...                            Error.
 */
LW_NTSTATUS 
LwNtSetInformationFile(
    LW_IN IO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_IN LW_PVOID FileInformation,
    LW_IN LW_ULONG Length,
    LW_IN FILE_INFORMATION_CLASS FileInformationClass
    );

//
// Additional Operations
//

#if 0
LW_NTSTATUS
LwNtQueryFullAttributesFile(
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_IN PIO_FILE_NAME FileName,
    LW_OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
    );
#endif

/**
 * @brief Query directory information
 *
 * Queries information about the entries in a directory.
 * Analogous to #IoQueryDirectoryFile().
 *
 * @param[in]     FileHandle           The file handle.
 * @param[in,out] AsyncControlBlock    Optional async control block. If specified,
 *                                     @a LW_STATUS_PENDING may be returned and
 *                                     @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock        Filled with result information on completion.
 * @param[out]    FileInformation      A buffer which is filled with the requested
 *                                     information.
 * @param[in]     Length               The size of @a FileInformation in bytes.
 * @param[in]     FileInformationClass The type of file information to query.
 * @param[in]     ReturnSingleEntry    If @a TRUE, only one entry will be returned.
 * @param[in]     FileSpec             An optional match specification which will constrain
 *                                     the returned entries.
 * @param[in]     RestartScan          Currently unused.  Must be @a FALSE.
 *
 * @retval LW_STATUS_SUCCESS              Success.
 * @retval LW_STATUS_PENDING              The operation will be completed asynchronously by
 *                                        invoking @a AsyncControlBlock->Callback.  The final result
 *                                        status can be obtained from @a IoStatusBlock->Status.
 * @retval LW_STATUS_BUFFER_TOO_SMALL     The passed buffer was too small to contain even a single
 *                                        entry of the requested information class.
 * @retval LW_STATUS_INVALID_INFO_CLASS   The specified information class was invalid.
 * @retval LW_STATUS_NO_MORE_ENTRIES      No more entries are available to return.
 * @retval LW_STATUS_NOT_A_DIRECTORY      The specified file was not a directory.
 * @retval ...                            Error.
 */
LW_NTSTATUS 
LwNtQueryDirectoryFile(
    LW_IN IO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_OUT LW_PVOID FileInformation,
    LW_IN LW_ULONG Length,
    LW_IN FILE_INFORMATION_CLASS FileInformationClass,
    LW_IN LW_BOOLEAN ReturnSingleEntry,
    LW_IN LW_OPTIONAL PIO_MATCH_FILE_SPEC FileSpec,
    LW_IN LW_BOOLEAN RestartScan
    );

/**
 * @brief Read directory change notifications
 *
 * Reads change notifications for a directory.
 * Analogous to #IoReadDirectoryChangeFile().
 *
 * @param[in]     FileHandle           The file handle.
 * @param[in,out] AsyncControlBlock    Optional async control block. If specified,
 *                                     @a LW_STATUS_PENDING may be returned and
 *                                     @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock        Filled with result information on completion.
 * @param[out]    Buffer               A buffer which is filled with change information.
 * @param[in]     Length               The size of @a Buffer in bytes.
 * @param[in]     WatchTree            If @a TRUE, recursive subdirectories will also be monitored.
 * @param[in]     NotifyFilter         A mask of notification events to watch for.
 * @param[in]     MaxBufferSize        An optional maximum internal buffer size.
 *                                     If specified, this provides a hint for how large an internal
 *                                     notification buffer to maintain for events that occur between
 *                                     reads.
 *
 * @retval LW_STATUS_SUCCESS              Success.
 * @retval LW_STATUS_PENDING              The operation will be completed asynchronously by
 *                                        invoking @a AsyncControlBlock->Callback.  The final result
 *                                        status can be obtained from @a IoStatusBlock->Status.
 * @retval LW_STATUS_BUFFER_TOO_SMALL     The passed buffer was too small to contain even a single
 *                                        notification.
 * @retval LW_STATUS_NOT_A_DIRECTORY      The specified file was not a directory.
 * @retval LW_STATUS_NOTIFY_ENUM_DIR      Change notifications have been lost; the application
 *                                        should re-enumerate the directory.
 * @retval ...
 */
NTSTATUS
LwNtReadDirectoryChangeFile(
    IN IO_FILE_HANDLE FileHandle,
    IN OUT OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    OUT PIO_STATUS_BLOCK IoStatusBlock,
    OUT PVOID Buffer,
    IN ULONG Length,
    IN BOOLEAN WatchTree,
    IN FILE_NOTIFY_CHANGE NotifyFilter,
    IN OPTIONAL PULONG MaxBufferSize
    );

/**
 * @brief Query volume information
 *
 * Queries for information about the physical volume on which a file resides.
 * Analogous to #IoQueryVolumeInformationFile().
 *
 * @param[in]     FileHandle           A file handle.  It is used only synecdochically to refer
 *                                     to the underlying volume.
 * @param[in,out] AsyncControlBlock    Optional async control block. If specified,
 *                                     @a LW_STATUS_PENDING may be returned and
 *                                     @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock        Filled with result information on completion.
 * @param[out]    FsInformation        A buffer which is filled with the requested
 *                                     information.
 * @param[in]     Length               The size of @a FsInformation in bytes.
 * @param[in]     FsInformationClass   The type of volume information to query.
 *
 * @retval LW_STATUS_SUCCESS            Success.
 * @retval LW_STATUS_PENDING            The operation will be completed asynchronously by
 *                                      invoking @a AsyncControlBlock->Callback.  The final result
 *                                      status can be obtained from @a IoStatusBlock->Status.
 * @retval LW_STATUS_BUFFER_TOO_SMALL   The passed buffer was too small to contain the
 *                                      requested information.
 * @retval LW_STATUS_BUFFER_OVERFLOW    The passed buffer was large enough to contain the fixed
 *                                      portion of the requested info structure, but not the
 *                                      variable-sized trailing portion.
 * @retval LW_STATUS_INVALID_INFO_CLASS The specified information class was invalid.
 * @retval ...                          Error.
 */
LW_NTSTATUS
LwNtQueryVolumeInformationFile(
    LW_IN IO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_OUT LW_PVOID FsInformation,
    LW_IN LW_ULONG Length,
    LW_IN FS_INFORMATION_CLASS FsInformationClass
    );

/**
 * @brief Set volume information
 *
 * Sets information about the physical volume on which a file resides.
 * Analogous to #IoSetVolumeInformationFile().
 *
 * @param[in]     FileHandle           A file handle.  It is used only synecdochically to refer
 *                                     to the underlying volume.
 * @param[in,out] AsyncControlBlock    Optional async control block. If specified,
 *                                     @a LW_STATUS_PENDING may be returned and
 *                                     @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock        Filled with result information on completion.
 * @param[in]     FsInformation        A buffer which is filled with the requested
 *                                     information.
 * @param[in]     Length               The size of @a FsInformation in bytes.
 * @param[in]     FsInformationClass   The type of volume information to query.
 *
 * @retval LW_STATUS_SUCCESS              Success.
 * @retval LW_STATUS_PENDING              The operation will be completed asynchronously by
 *                                        invoking @a AsyncControlBlock->Callback.  The final result
 *                                        status can be obtained from @a IoStatusBlock->Status.
 * @retval LW_STATUS_INFO_LENGTH_MISMATCH The passed buffer had the wrong length for the specified
 *                                        information class.
 * @retval LW_STATUS_INVALID_INFO_CLASS   The specified information class was invalid.
 * @retval ...                            Error.
 */
LW_NTSTATUS
LwNtSetVolumeInformationFile(
    LW_IN IO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_IN LW_PVOID FsInformation,
    LW_IN LW_ULONG Length,
    LW_IN FS_INFORMATION_CLASS FsInformationClass
    );

/**
 * @brief Lock file region
 *
 * Locks a region within a file.  Analogous to #IoLockFile().
 *
 * @param[in]     FileHandle           The file handle.
 * @param[in,out] AsyncControlBlock    Optional async control block. If specified,
 *                                     @a LW_STATUS_PENDING may be returned and
 *                                     @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock        Filled with result information on completion.
 * @param[in]     ByteOffset           The offset within the file of the region to lock.
 * @param[in]     Length               The length of the region.
 * @param[in]     Key                  Currently unused.  Must be @a 0.
 * @param[in]     FailImmediately      If @a TRUE, a conflicting lock will cause the operation
 *                                     to fail immediately rather than waiting for it to be
 *                                     unlocked.
 * @param[in]     ExclusiveLock        If @a TRUE, the lock is exclusive.
 *
 * @retval LW_STATUS_SUCCESS            Success.
 * @retval LW_STATUS_PENDING            The operation will be completed asynchronously by
 *                                      invoking @a AsyncControlBlock->Callback.  The final result
 *                                      status can be obtained from @a IoStatusBlock->Status.
 * @retval LW_STATUS_INVALID_LOCK_RANGE The specified range is invalid.
 * @retval LW_STATUS_LOCK_NOT_GRANTED   The lock could not be granted due to a conflict.
 * @retval ...                          Error.
 */
LW_NTSTATUS 
LwNtLockFile(
    LW_IN IO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_IN LONG64 ByteOffset,
    LW_IN LONG64 Length,
    LW_IN LW_ULONG Key,
    LW_IN LW_BOOLEAN FailImmediately,
    LW_IN LW_BOOLEAN ExclusiveLock
    );

/**
 * @brief Unlock file region
 *
 * Unlocks a region within a file.  Analogous to #IoUnlockFile().
 *
 * @param[in]     FileHandle           The file handle.
 * @param[in,out] AsyncControlBlock    Optional async control block. If specified,
 *                                     @a LW_STATUS_PENDING may be returned and
 *                                     @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock        Filled with result information on completion.
 * @param[in]     ByteOffset           The offset within the file of the region to lock.
 * @param[in]     Length               The length of the region.
 * @param[in]     Key                  Currently unused.  Must be @a 0.
 *
 * @retval LW_STATUS_SUCCESS            Success.
 * @retval LW_STATUS_PENDING            The operation will be completed asynchronously by
 *                                      invoking @a AsyncControlBlock->Callback.  The final result
 *                                      status can be obtained from @a IoStatusBlock->Status.
 * @retval LW_STATUS_INVALID_LOCK_RANGE The specified range is invalid.
 * @retval LW_STATUS_RANGE_NOT_LOCKED   The specified range did not contain a lock.
 * @retval ...                          Error.
 */
LW_NTSTATUS 
LwNtUnlockFile(
    LW_IN IO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_IN LONG64 ByteOffset,
    LW_IN LONG64 Length,
    LW_IN LW_ULONG Key
    );

//
// Namespace Operations
//
// These are in flux due NT vs POSIX issues.
//

#if 0
LW_NTSTATUS
LwNtRemoveDirectoryFile(
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_IN PIO_FILE_NAME FileName
    );

LW_NTSTATUS
LwNtDeleteFile(
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_IN PIO_FILE_NAME FileName
    );

LW_NTSTATUS
LwNtLinkFile(
    LW_IN PIO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_IN PIO_FILE_NAME LinkName
    );

LW_NTSTATUS
LwNtRenameFile(
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_IN PIO_FILE_NAME FromName,
    LW_IN PIO_FILE_NAME ToName
    );
#endif

//
// Advanced Operations
//

/**
 * @brief Query quota information
 *
 * Enumerates information about quotas on a file.
 * Analogous to #IoQueryQuotaInformationFile().
 *
 * @param[in]     FileHandle          The file handle.
 * @param[in,out] AsyncControlBlock   Optional async control block. If specified,
 *                                    @a LW_STATUS_PENDING may be returned and
 *                                    @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock       Filled with result information on completion.
 * @param[out]    Buffer              A buffer to fill with quota information.
 * @param[in]     Length              The size of @a Buffer in bytes.
 * @param[in]     ReturnSingleEntry   If @a TRUE, only a single quota entry will be returned.
 * @param[in]     SidList             If provided, contains a list of SIDs for which quota
 *                                    information should be returned.
 * @param[in]     SidListLength       The size in bytes of @a SidList, or @a 0.
 * @param[in]     StartSid            If provided, contains a single SID from which enumeration
 *                                    should proceed.
 * @param[in]     RestartScan         If @a TRUE, enumeration will be restarted.
 *
 * @retval LW_STATUS_SUCCESS                 Success.
 * @retval LW_STATUS_PENDING                 The operation will be completed asynchronously by
 *                                           invoking @a AsyncControlBlock->Callback.  The final result
 *                                           status can be obtained from @a IoStatusBlock->Status.
 *                                           requested information.
 * @retval LW_STATUS_INVALID_DEVICE_REQUEST  Quotas are not enabled on the underlying volume.
 * @retval LW_STATUS_INVALID_SID             @a StartSid contained an invalid SID.
 * @retval LW_STATUS_QUOTA_LIST_INCONSISTENT @a SidList was not properly formed.
 * @retval LW_STATUS_BUFFER_TOO_SMALL        The provided buffer was too small to hold even a single entry.
 */
LW_NTSTATUS
LwNtQueryQuotaInformationFile(
    LW_IN IO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_OUT LW_PVOID Buffer,
    LW_IN LW_ULONG Length,
    LW_IN LW_BOOLEAN ReturnSingleEntry,
    LW_IN LW_OPTIONAL LW_PVOID SidList,
    LW_IN LW_ULONG SidListLength,
    LW_IN LW_OPTIONAL PSID StartSid,
    LW_IN LW_BOOLEAN RestartScan
    );

/**
 * @brief Set quota information
 *
 * Sets quota information on a file.  Analogous to #IoSetQuotaInformationFile().
 *
 * @param[in]     FileHandle          The file handle.
 * @param[in,out] AsyncControlBlock   Optional async control block. If specified,
 *                                    @a LW_STATUS_PENDING may be returned and
 *                                    @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock       Filled with result information on completion.
 * @param[out]    Buffer              The quota information to set.
 * @param[in]     Length              The size of @a Buffer in bytes.
 *
 * @retval LW_STATUS_SUCCESS                 Success.
 * @retval LW_STATUS_PENDING                 The operation will be completed asynchronously by
 *                                           invoking @a AsyncControlBlock->Callback.  The final result
 *                                           status can be obtained from @a IoStatusBlock->Status.
 * @retval LW_STATUS_INVALID_DEVICE_REQUEST  Quotas are not enabled on the underlying volume.
 * @retval LW_STATUS_QUOTA_LIST_INCONSISTENT @a Buffer was not properly formed.
 * @retval LW_STATUS_BUFFER_TOO_SMALL        The provided buffer was too small to hold even a single entry.
 */
LW_NTSTATUS
LwNtSetQuotaInformationFile(
    LW_IN IO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_IN LW_PVOID Buffer,
    LW_IN LW_ULONG Length
    );

/**
 * @brief Query file security descriptor
 *
 * Queries the security descriptor for a file.  Analogous to
 * #IoQuerySecurityFile().
 *
 * @param[in]     FileHandle          The file handle.
 * @param[in,out] AsyncControlBlock   Optional async control block. If specified,
 *                                    @a LW_STATUS_PENDING may be returned and
 *                                    @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock       Filled with result information on completion.
 * @param[in]     SecurityInformation A mask indicating which parts of the security descriptor
 *                                    should be queried.
 * @param[out]    SecurityDescriptor  A buffer which is filled with the requested
 *                                    information.
 * @param[in]     Length              The size of @a SecurityDescriptor in bytes.
 *
 * @retval LW_STATUS_SUCCESS            Success.
 * @retval LW_STATUS_PENDING            The operation will be completed asynchronously by
 *                                      invoking @a AsyncControlBlock->Callback.  The final result
 *                                      status can be obtained from @a IoStatusBlock->Status.
 * @retval LW_STATUS_BUFFER_TOO_SMALL   The passed buffer was too small to contain the
 *                                      requested information.
 * @retval LW_STATUS_ACCESS_DENIED      The handle was not opened with appropriate access to read
 *                                      the requested information.
 * @retval ...                          Error.
 */
LW_NTSTATUS
LwNtQuerySecurityFile(
    LW_IN IO_FILE_HANDLE  FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_IN SECURITY_INFORMATION SecurityInformation,
    LW_OUT PSECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor,
    LW_IN LW_ULONG Length
    ); 

/**
 * @brief Update file security descriptor
 *
 * Updates the security descriptor for a file.
 * Analogous to #IoSetSecurityFile().
 *
 * @param[in]     FileHandle          The file handle.
 * @param[in,out] AsyncControlBlock   Optional async control block. If specified,
 *                                    @a LW_STATUS_PENDING may be returned and
 *                                    @a AsyncControlBlock->AsyncCancelContext set.
 * @param[out]    IoStatusBlock       Filled with result information on completion.
 * @param[in]     SecurityInformation A mask indicating which parts of the security descriptor
 *                                    should be updated.
 * @param[in]     SecurityDescriptor  A buffer which contains the security descriptor information
 *                                    to be set.
 * @param[in]     Length              The size of @a SecurityDescriptor in bytes.
 *
 * @retval LW_STATUS_SUCCESS            Success.
 * @retval LW_STATUS_PENDING            The operation will be completed asynchronously by
 *                                      invoking @a AsyncControlBlock->Callback.  The final result
 *                                      status can be obtained from @a IoStatusBlock->Status.
 * @retval LW_STATUS_ACCESS_DENIED      The handle was not opened with appropriate access to write
 *                                      the requested information.
 * @retval ...                          Error.
 */
LW_NTSTATUS
LwNtSetSecurityFile(
    LW_IN IO_FILE_HANDLE FileHandle,
    LW_IN LW_OUT LW_OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    LW_OUT PIO_STATUS_BLOCK IoStatusBlock,
    LW_IN SECURITY_INFORMATION SecurityInformation,
    LW_IN PSECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor,
    LW_IN LW_ULONG Length
    ); 

/**
 * @brief Cancel asynchronous operation
 *
 * Cancels an outstanding asynchronous operation.  This is
 * analogous to #IoCancelAsyncCancelContext(), but actually
 * cancels the call into lwio itself.  Call cancellation is
 * not acknowledged, so no return value is provided.
 *
 * The cancel context must still be released with
 * #LwNtDereferenceAsyncCancelContext().
 *
 * @param[in] pAsyncCancelContext The async cancel context for the operation to cancel.
 */
VOID
LwNtCancelAsyncCancelContext(
    LW_IN PIO_ASYNC_CANCEL_CONTEXT pAsyncCancelContext
    );

/**
 * @brief Release async cancel context
 *
 * Releases the async cancel context handle for an operation.
 *
 * @param[in,out] ppAsyncCancelContext The async cancel context.
 */
VOID
LwNtDereferenceAsyncCancelContext(
    LW_IN LW_OUT PIO_ASYNC_CANCEL_CONTEXT* ppAsyncCancelContext
    );

// TODO: QueryEaFile and SetEaFile.

/*@}*/

LW_END_EXTERN_C

#ifndef LW_STRICT_NAMESPACE

#define NtCreateNamedPipeFile           LwNtCreateNamedPipeFile
#define NtCreateFile                    LwNtCreateFile
#define NtCloseFile                     LwNtCloseFile
#define NtAsyncCloseFile                LwNtAsyncCloseFile
#define NtReadFile                      LwNtReadFile
#define NtWriteFile                     LwNtWriteFile
#define NtDeviceIoControlFile           LwNtDeviceIoControlFile
#define NtFsControlFile                 LwNtFsControlFile
#define NtFlushBuffersFile              LwNtFlushBuffersFile
#define NtQueryInformationFile          LwNtQueryInformationFile
#define NtSetInformationFile            LwNtSetInformationFile
#define NtQueryFullAttributesFile       LwNtQueryFullAttributesFile
#define NtQueryDirectoryFile            LwNtQueryDirectoryFile
#define NtReadDirectoryChangeFile       LwNtReadDirectoryChangeFile
#define NtQueryVolumeInformationFile    LwNtQueryVolumeInformationFile
#define NtSetVolumeInformationFile      LwNtSetVolumeInformationFile
#define NtLockFile                      LwNtLockFile
#define NtUnlockFile                    LwNtUnlockFile
#define NtRemoveDirectoryFile           LwNtRemoveDirectoryFile
#define NtDeleteFile                    LwNtDeleteFile
#define NtLinkFile                      LwNtLinkFile
#define NtRenameFile                    LwNtRenameFile
#define NtQueryQuotaInformationFile     LwNtQueryQuotaInformationFile
#define NtSetQuotaInformationFile       LwNtSetQuotaInformationFile
#define NtQuerySecurityFile             LwNtQuerySecurityFile
#define NtSetSecurityFile               LwNtSetSecurityFile

#endif /* ! LW_STRICT_NAMESPACE */

#endif /* __NT_FILE_API__ */



/*
local variables:
mode: c
c-basic-offset: 4
indent-tabs-mode: nil
tab-width: 4
end:
*/
