/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
 * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: *
 * Editor Settings: expandtabs and use 4 spaces for indentation */

/*
 * Copyright Likewise Software    2004-2009
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program 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 General Public License
 * for more details.  You should have received a copy of the GNU 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
 * 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@likewisesoftware.com
 */

/*
 * Copyright (C) Likewise Software. All rights reserved.
 *
 * Module Name:
 *
 *        elementsapi.h
 *
 * Abstract:
 *
 *        Likewise Input Output (LWIO) - SRV
 *
 *        Elements API
 *
 * Authors: Sriram Nambakam (snambakam@likewisesoftware.com)
 *
 */

#ifndef __ELEMENTSAPI_H__
#define __ELEMENTSAPI_H__

#include <lw/list.h>
#include <elements_types.h>
#include <lwio/lwiofsctl.h>
#include <lwio/ioapi.h>

#define SRV_LRU_CAPACITY             64

#define SMB_FIND_CLOSE_AFTER_REQUEST 0x1
#define SMB_FIND_CLOSE_IF_EOS        0x2
#define SMB_FIND_RETURN_RESUME_KEYS  0x4
#define SMB_FIND_CONTINUE_SEARCH     0x8
#define SMB_FIND_WITH_BACKUP_INTENT  0x10

typedef UCHAR SMB_OPLOCK_LEVEL;

#define SMB_OPLOCK_LEVEL_NONE  0x00
#define SMB_OPLOCK_LEVEL_I     0x01
#define SMB_OPLOCK_LEVEL_BATCH 0x02
#define SMB_OPLOCK_LEVEL_II    0x03

#define SMB_OPLOCK_LEVEL_BROKEN_TO_NONE     0x00
#define SMB_OPLOCK_LEVEL_BROKEN_TO_LEVEL_II 0x01


typedef UCHAR SMB2_OPLOCK_LEVEL;

#define SMB2_OPLOCK_LEVEL_LEASE 0xFF
#define SMB2_OPLOCK_LEVEL_BATCH 0x09
#define SMB2_OPLOCK_LEVEL_I     0x08
#define SMB2_OPLOCK_LEVEL_II    0x01
#define SMB2_OPLOCK_LEVEL_NONE  0x00

#define SMB2_OPLOCK_LEVEL_BROKEN_TO_NONE     0x00
#define SMB2_OPLOCK_LEVEL_BROKEN_TO_LEVEL_II 0x01

#define SMB2_LEASE_WRITE_CACHING  0x04
#define SMB2_LEASE_HANDLE_CACHING 0x02
#define SMB2_LEASE_READ_CACHING   0x01
#define SMB2_LEASE_NONE           0x00

#define SMB2_LEASE_BREAK_NOTIFY_ACK_REQUIRED   0x01

#define SMB_CN_MAX_BUFFER_SIZE 0x00010000

typedef ULONG SMB_SESSION_FLAG;

#define SMB_SESSION_FLAG_GUEST         0x00000001
#define SMB_SESSION_FLAG_NO_ENCRYPTION 0x00000002

typedef VOID (*PFN_SRV_FREE_OPLOCK)(HANDLE  hOplock);
typedef VOID (*PFN_SRV_CANCEL_OPLOCK)(HANDLE hOplock);
typedef NTSTATUS (*PFN_SRV_REPARENT_OPLOCK)(
                        HANDLE hOplock,
                        PLWIO_SRV_FILE_2 pFile,
                        PSRV_DURABLE_ENTRY pEntry
                        );
typedef VOID (*PFN_SRV_GET_OPLOCK_LEVEL)(
                    HANDLE hOplock,
                    PUCHAR OplockLevel,
                    PULONG LeaseState);
typedef VOID (*PFN_LWIO_SRV_FREE_BRL_STATE_LIST)(HANDLE hBRLStateList);
typedef VOID (*PFN_LWIO_SRV_CANCEL_ASYNC_STATE)(HANDLE hAsyncState);
typedef VOID (*PFN_LWIO_SRV_FREE_ASYNC_STATE)(HANDLE hAsyncState);

typedef ULONG SRV_OBJECT_FLAGS, *PSRV_OBJECT_FLAGS;

#define SRV_OBJECT_FLAG_RUNDOWN     0x00000001
#define SRV_OBJECT_FLAG_IN_PARENT   0x00000002

typedef BOOLEAN (*PFN_SRV_CONNECTION_ENUM_CALLBACK)(
    PLWIO_SRV_CONNECTION pConnection,
    PVOID pContext
    );

typedef BOOLEAN (*PFN_SRV_SESSION_ENUM_CALLBACK)(
    PLWIO_SRV_SESSION pSession,
    PVOID pContext
    );

typedef BOOLEAN (*PFN_SRV_SESSION_2_ENUM_CALLBACK)(
    PLWIO_SRV_SESSION_2 pSession,
    PVOID pContext
    );

typedef BOOLEAN (*PFN_SRV_TREE_ENUM_CALLBACK)(
    PLWIO_SRV_TREE pTree,
    PVOID pContext
    );

typedef BOOLEAN (*PFN_SRV_TREE_2_ENUM_CALLBACK)(
    PLWIO_SRV_TREE_2 pTree,
    PVOID pContext
    );

typedef BOOLEAN (*PFN_SRV_FILE_ENUM_CALLBACK)(
    PLWIO_SRV_FILE pFile,
    PVOID pContext
    );

typedef BOOLEAN (*PFN_SRV_FILE_2_ENUM_CALLBACK)(
    PLWIO_SRV_FILE_2 pFile,
    PVOID pContext
    );

typedef BOOLEAN (*PFN_SRV_ASYNC_STATE_ENUM_CALLBACK)(
    PLWIO_ASYNC_STATE pAsyncState,
    PVOID pContext
    );

typedef VOID (*PFN_SRV_FILE_CANCEL_ASYNC_OPERATIONS)(PLWIO_SRV_FILE pFile);

typedef struct __SMB2_FID
{
    ULONG64 ullPersistentId;
    ULONG64 ullVolatileId;
} __attribute__((__packed__)) SMB2_FID;

typedef enum
{
    SRV_RESOURCE_TYPE_UNKNOWN = 0,
    SRV_RESOURCE_TYPE_CONNECTION,
    SRV_RESOURCE_TYPE_TREE,
    SRV_RESOURCE_TYPE_FILE
} SRV_RESOURCE_TYPE;

typedef struct _SRV_RESOURCE_ATTRIBUTES
{
    SMB_PROTOCOL_VERSION protocolVersion;

    ULONG        ulConnectionResourceId;

    union
    {

        USHORT   usUid;
        ULONG64  ullUid;

    } sessionId;

    union
    {

        USHORT   usTid;
        ULONG    ulTid;

    } treeId;

    union
    {

        PUSHORT   pFid1;
        PSMB2_FID pFid2;

    } fileId;

} SRV_RESOURCE_ATTRIBUTES, *PSRV_RESOURCE_ATTRIBUTES;

typedef struct _SRV_RESOURCE
{
    LONG                     refCount;

    ULONG                    ulResourceId;

    SRV_RESOURCE_TYPE        resourceType;

    PSRV_RESOURCE_ATTRIBUTES pAttributes;

} SRV_RESOURCE, *PSRV_RESOURCE;

typedef NTSTATUS (*PFN_ENUM_RESOURCES)(
                    PSRV_RESOURCE pResource,
                    PVOID         pUserData,
                    PBOOLEAN      pbContinue
                    );

typedef ULONG SRV_MPX_TRACKING_FLAGS, *PSRV_MPX_TRACKING_FLAGS;

#define SRV_MPX_TRACKING_FLAG_IN_TRACKER    0x00000001
#define SRV_MPX_TRACKING_FLAG_CANCELLED     0x00000002
// for debugging only:
#define SRV_MPX_TRACKING_FLAG_EXECUTING     0x00000004

typedef struct _SRV_MPX_TRACKING_STATE
{
    SRV_MPX_TRACKING_FLAGS flags;

    // Require MID + PID to be unique within tracker (connection).
    ULONG ulPid;
    USHORT usMid;

    // Must match UID + TID when doing a cancel.
    USHORT usUid;
    USHORT usTid;

    // SRV_MPX_TRACKER's list:
    LW_LIST_LINKS mpxTrackerListEntry;

} SRV_MPX_TRACKING_STATE, *PSRV_MPX_TRACKING_STATE;

typedef struct _SRV_ASYNC_CLOSE_FILE_TRACKER {
    pthread_mutex_t Mutex;
    pthread_mutex_t* pMutex;
    pthread_cond_t Condition;
    pthread_cond_t* pCondition;
    LONG PendingCount;
} SRV_ASYNC_CLOSE_FILE_TRACKER, *PSRV_ASYNC_CLOSE_FILE_TRACKER;

typedef struct _SRV_ASYNC_CLOSE_FILE_STATE {
    PSRV_ASYNC_CLOSE_FILE_TRACKER pTracker;
    IO_ASYNC_CONTROL_BLOCK AsyncControlBlock;
    IO_STATUS_BLOCK IoStatusBlock;
} SRV_ASYNC_CLOSE_FILE_STATE, *PSRV_ASYNC_CLOSE_FILE_STATE;

typedef struct _LWIO_ASYNC_STATE
{
    pthread_rwlock_t               mutex;
    pthread_rwlock_t*              pMutex;

    LONG                           refcount;

    PLWIO_ASYNC_STATE              pRundownNext;

    ULONG64                        ullAsyncId;
    ULONG64                        ullCommandSequence;
    USHORT                         usCommand;

    HANDLE                         hAsyncState;

    PFN_LWIO_SRV_FREE_ASYNC_STATE   pfnFreeAsyncState;
    PFN_LWIO_SRV_CANCEL_ASYNC_STATE pfnCancelAsyncState;

} LWIO_ASYNC_STATE;

typedef struct _LWIO_SRV_FILE
{
    pthread_rwlock_t        mutex;
    pthread_rwlock_t*       pMutex;

    LONG                    refcount;

    // Parent
    PLWIO_SRV_TREE          pTree;
    SRV_OBJECT_FLAGS        objectFlags;
    PLWIO_SRV_FILE          pRundownNext;

    USHORT                  fid;

    SRV_RESOURCE            resource;
    SRV_RESOURCE_ATTRIBUTES resourceAttrs;

    IO_FILE_HANDLE          hFile;
    PIO_FILE_NAME           pFilename; // physical path on server
    PWSTR                   pwszFilename; // requested path
    ACCESS_MASK             desiredAccess;
    LONG64                  allocationSize;
    FILE_ATTRIBUTES         fileAttributes;
    FILE_SHARE_FLAGS        shareAccess;
    FILE_CREATE_DISPOSITION createDisposition;
    FILE_CREATE_OPTIONS     createOptions;
    LONG64                  SnapshotTime;

    UCHAR                   ucCurrentOplockLevel;

    ULONG                   ulPermissions;
    ULONG                   ulNumLocks;

    HANDLE                  hOplock;

    HANDLE                           hCancellableBRLStateList;
    PFN_LWIO_SRV_FREE_BRL_STATE_LIST pfnFreeBRLStateList;

    ULONG64                        ullLastFailedLockOffset;

    PFN_SRV_FILE_CANCEL_ASYNC_OPERATIONS pfnCancelAsyncOperationsFile;

    PSRV_ASYNC_CLOSE_FILE_STATE pAsyncCloseFileState;

    BOOLEAN bIsBlockingIdleTimeout;

} LWIO_SRV_FILE;

typedef struct _LWIO_SRV_SEARCH_SPACE_2
{
    UCHAR                  ucInfoClass;
    UCHAR                  ucSearchFlags;
    ULONG                  ulFileIndex;
    PWSTR                  pwszSearchPatternRaw;
    PWSTR                  pwszSearchPatternRef;
    ULONG                  ulSearchPatternLength;
    PWSTR                  pwszSearchPattern;
    PBYTE                  pFileInfo;
    PBYTE                  pFileInfoCursor;
    USHORT                 usFileInfoLen;
    BOOLEAN                bUseLongFilenames;
    LONG64                 llSearchIndex;

} LWIO_SRV_SEARCH_SPACE_2, *PLWIO_SRV_SEARCH_SPACE_2;

typedef struct _LWIO_SRV_OPEN_STATE_2
{
    ACCESS_MASK             desiredAccess;
    LONG64                  allocationSize;
    FILE_ATTRIBUTES         fileAttributes;
    FILE_SHARE_FLAGS        shareAccess;
    FILE_CREATE_DISPOSITION createDisposition;
    FILE_CREATE_OPTIONS     createOptions;
    LONG64                  SnapshotTime;
    ULONG                   DurableTimeout;
} LWIO_SRV_OPEN_STATE_2, *PLWIO_SRV_OPEN_STATE_2;

typedef struct _LWIO_SRV_FILE_2
{
    pthread_rwlock_t        mutex;
    pthread_rwlock_t*       pMutex;

    LONG                    refcount;

    // Parent
    PLWIO_SRV_TREE_2        pTree;
    SRV_OBJECT_FLAGS        objectFlags;
    PLWIO_SRV_FILE_2        pRundownNext;

    SMB2_FID                fid;

    SRV_RESOURCE            resource;
    SRV_RESOURCE_ATTRIBUTES resourceAttrs;

    LWIO_SRV_OPEN_STATE_2   OpenState;

    IO_FILE_HANDLE          hFile;
    unsigned                bReleaseOnly:1; // Only need to release hFile, not close it
    PIO_FILE_NAME           pFilename; // physical path on server
    PWSTR                   pwszFilename; // requested path

    LWIO_SRV_SEARCH_SPACE_2  searchSpace;
    PLWIO_SRV_SEARCH_SPACE_2 pSearchSpace;

    ULONG                    ulPermissions;
    ULONG                    ulNumLocks;

    BOOLEAN                  bIsDurable;
    BOOLEAN                  bIsClosing;

    HANDLE                       hOplock;
    PSRV_ASYNC_CLOSE_FILE_STATE  pAsyncCloseFileState;
    PSRV_DURABLE_ENTRY           pDurable;

    BOOLEAN bIsBlockingIdleTimeout;

} LWIO_SRV_FILE_2;

typedef struct _LWIO_SRV_TREE
{
    LONG                    refcount;

    pthread_rwlock_t        mutex;
    pthread_rwlock_t*       pMutex;

    // Parent
    PLWIO_SRV_SESSION       pSession;
    SRV_OBJECT_FLAGS        objectFlags;
    PLWIO_SRV_TREE          pRundownNext;

    USHORT                  tid;
    USHORT                  uid;

    SRV_RESOURCE            resource;
    SRV_RESOURCE_ATTRIBUTES resourceAttrs;

    PSRV_SHARE_INFO         pShareInfo;

    IO_FILE_HANDLE          hFile;

    PLWIO_SRV_FILE          lruFile[SRV_LRU_CAPACITY];

    PLWRTL_RB_TREE          pFileCollection;

    ULONG                   ulNumOpenFiles;

    PLWRTL_RB_TREE          pAsyncStateCollection;

    SRV_SHARE_INFO_REGISTRATION ShareInfoRegistration;

    BOOLEAN                 UnderstandSnapshots;

} LWIO_SRV_TREE;

typedef struct _LWIO_SRV_TREE_2
{
    LONG                    refcount;

    pthread_rwlock_t        mutex;
    pthread_rwlock_t*       pMutex;

    // Parent
    PLWIO_SRV_SESSION_2     pSession;
    SRV_OBJECT_FLAGS        objectFlags;
    PLWIO_SRV_TREE_2        pRundownNext;

    ULONG                   ulTid;
    ULONG64                 ullUid;

    SRV_RESOURCE            resource;
    SRV_RESOURCE_ATTRIBUTES resourceAttrs;

    PSRV_SHARE_INFO         pShareInfo;

    IO_FILE_HANDLE              hFile;
    PSRV_ASYNC_CLOSE_FILE_STATE pAsyncCloseFileState;

    PLWIO_SRV_FILE_2        lruFile[SRV_LRU_CAPACITY];

    PLWRTL_RB_TREE          pFileCollection;

    ULONG                   ulNumOpenFiles;

    ULONG64                 ullNextAvailableFid;

    SRV_SHARE_INFO_REGISTRATION ShareInfoRegistration;

    BOOLEAN                 UnderstandSnapshots;

} LWIO_SRV_TREE_2;

typedef struct _LWIO_SRV_SESSION
{
    LONG              refcount;

    pthread_rwlock_t  mutex;
    pthread_rwlock_t* pMutex;

    pthread_mutex_t   GssMutex;
    pthread_mutex_t*  pGssMutex;

    HANDLE            hGssNegotiate;

    // Parent
    PLWIO_SRV_CONNECTION pConnection;
    SRV_OBJECT_FLAGS  objectFlags;
    PLWIO_SRV_SESSION pRundownNext;

    USHORT            uid;

    ULONG             ulConnectionResourceId;

    LONG64            llBirthTime;

    PLWIO_SRV_TREE    lruTree[SRV_LRU_CAPACITY];

    PLWRTL_RB_TREE    pTreeCollection;

    HANDLE            hFinderRepository;

    PWSTR             pwszClientPrincipalName;
    PWSTR             pNetbiosDomain;
    PWSTR             pSamAccountName;

    LONG64            llLastActivityTime;

    ULONG             ulUserFlags;

    PIO_CREATE_SECURITY_CONTEXT pIoSecurityContext;

    PVOID             pOEMSession;
    ULONG             ulOEMSessionLength;

    PBYTE             pSessionKey;
    ULONG             ulSessionKeyLength;
} LWIO_SRV_SESSION;

typedef struct _LWIO_SRV_SESSION_2
{
    // Links entry into global hash table.
    LW_HASHTABLE_NODE HashNode;

    LONG              refcount;

    pthread_rwlock_t  mutex;
    pthread_rwlock_t* pMutex;

    pthread_mutex_t   GssMutex;
    pthread_mutex_t*  pGssMutex;

    HANDLE            hGssNegotiate;

    // Parent
    PLWIO_SRV_CONNECTION pConnection;
    SRV_OBJECT_FLAGS     objectFlags;
    PLWIO_SRV_SESSION_2  pRundownNext;

    ULONG64           ullUid;

    ULONG             ulConnectionResourceId;

    LONG64            llBirthTime;

    PLWIO_SRV_TREE_2  lruTree[SRV_LRU_CAPACITY];

    PLWRTL_RB_TREE    pTreeCollection;

    ULONG             ulNextAvailableTid;

    PWSTR             pwszClientPrincipalName;
    PWSTR             pNetbiosDomain;
    PWSTR             pSamAccountName;

    LONG64            llLastActivityTime;

    ULONG             ulUserFlags;

    PIO_CREATE_SECURITY_CONTEXT   pIoSecurityContext;

    PVOID             pOEMSession;
    ULONG             ulOEMSessionLength;

    PBYTE             pSessionKey;
    ULONG             ulSessionKeyLength;

    BOOLEAN           bRequireSecuritySignatures;

    SMB2_CRYPTO_KEY   SigningKey;
} LWIO_SRV_SESSION_2;

typedef enum
{
    LWIO_SRV_CONN_STATE_INITIAL = 0,
    LWIO_SRV_CONN_STATE_NEGOTIATE,
    LWIO_SRV_CONN_STATE_READY,
    LWIO_SRV_CONN_STATE_INVALID
} LWIO_SRV_CONN_STATE;

typedef enum
{
    SRV_ZCT_STATE_UNKNOWN = 0,
    SRV_ZCT_STATE_NOT_ZCT,
    SRV_ZCT_STATE_IS_ZCT
} SRV_ZCT_STATE, *PSRV_ZCT_STATE;

typedef struct _SRV_PROPERTIES
{
    USHORT  preferredSecurityMode;
    BOOLEAN bEncryptPasswords;
    BOOLEAN bEnableSecuritySignatures;
    BOOLEAN bRequireSecuritySignatures;
    ULONG   ulZctReadThreshold;
    ULONG   ulZctWriteThreshold;
    USHORT  usMaxMpxCount;
    USHORT  usMaxNumberVCs;
    ULONG   ulMaxBufferSize;
    ULONG   ulMaxBufferSize_SMB_V2;
    ULONG   ulMaxBufferSizeLargeMtu_SMB_V2;
    ULONG   ulMaxRawSize;
    ULONG   ulCapabilities;
    uuid_t  GUID;

} SRV_PROPERTIES, *PSRV_PROPERTIES;

typedef struct _SRV_CLIENT_PROPERITES
{
    BOOLEAN bIsInitialized;
    USHORT  usMaxBufferSize;
    USHORT  usMaxMpxCount;
    USHORT  usVcNumber;
    ULONG   ulSessionKey;
    ULONG   ulCapabilities;
    BOOLEAN bEnableSecuritySignatures;
    BOOLEAN bRequireSecuritySignatures;
    PWSTR   pwszNativeOS;
    PWSTR   pwszNativeLanMan;
    PWSTR   pwszNativeDomain;
    uuid_t  GUID;

} SRV_CLIENT_PROPERTIES, *PSRV_CLIENT_PROPERTIES;

typedef struct _SRV_SOCKET *PLWIO_SRV_SOCKET;
typedef VOID (*PFN_SRV_SOCKET_FREE)(PLWIO_SRV_SOCKET pSocket);
typedef VOID (*PFN_SRV_SOCKET_DISCONNECT)(PLWIO_SRV_SOCKET pSocket);
typedef VOID (*PFN_SRV_SOCKET_GET_ADDRESS)(PLWIO_SRV_SOCKET pSocket, const struct sockaddr** ppAddress, SOCKLEN_TYPE* pulAddressLength);
typedef VOID (*PFN_SRV_CONNECTION_IO_COMPLETE)(PVOID pContext, NTSTATUS Status);
typedef VOID (*PFN_SRV_SOCKET_RESET_TIMEOUT)(PLWIO_SRV_SOCKET pSocket, BOOLEAN bIsEnabled, ULONG ulTimeoutSeconds);
struct _SRV_EXEC_CONTEXT;

typedef struct _SRV_CONNECTION_SOCKET_DISPATCH {
    PFN_SRV_SOCKET_FREE pfnFree;
    PFN_SRV_SOCKET_DISCONNECT pfnDisconnect;
    PFN_SRV_SOCKET_GET_ADDRESS pfnGetClientAddress;
    PFN_SRV_SOCKET_GET_ADDRESS pfnGetServerAddress;
    PFN_SRV_SOCKET_RESET_TIMEOUT pfnResetTimeout;
} SRV_CONNECTION_SOCKET_DISPATCH, *PSRV_CONNECTION_SOCKET_DISPATCH;

typedef struct _SRV_CREDITOR *PSRV_CREDITOR;

typedef struct _SRV_CONNECTION
{
    LONG                    refCount;

    pthread_rwlock_t        mutex;
    pthread_rwlock_t*       pMutex;

    LWIO_SRV_CONN_STATE     state;

    // Immutable for lifetime of connection.
    SRV_RESOURCE            resource;
    const struct sockaddr*  pClientAddress;
    SOCKLEN_TYPE            clientAddrLen;
    const struct sockaddr*  pServerAddress;
    SOCKLEN_TYPE            serverAddrLen;
    PLWIO_SRV_SOCKET        pSocket;
    PSRV_CONNECTION_SOCKET_DISPATCH pSocketDispatch;

    SRV_PROPERTIES          serverProperties;
    SRV_CLIENT_PROPERTIES   clientProperties;

    SMB_PROTOCOL_VERSION    protocolVer;
    SMB_PROTOCOL_DIALECT    Dialect;

    ULONG                   ulSequence;

    USHORT                  usNextAvailableUid;

    // Invariant
    // Not owned
    HANDLE                  hPacketAllocator;

    struct
    {
        BOOLEAN             bNeedHeader;
        BYTE                HeaderBuffer[sizeof(NETBIOS_HEADER)];
        size_t              sNumBytesToRead;
        size_t              sOffset;
        PSMB_PACKET         pRequestPacket;
        SRV_ZCT_STATE       zctState;
        struct _SRV_EXEC_CONTEXT* pContinueExecContext;
        PFN_SRV_CONNECTION_IO_COMPLETE pfnZctCallback;
        PVOID               pZctCallbackContext;
        ULONG               ulSkipBytes;
    } readerState;

    PBYTE                   pSMB1SigningKey;
    ULONG                   ulSMB1SigningKeyLength;

    // Server-wide state
    SRV_SHARES_HANDLE       hShares;
    PVOID                   pProtocolTransportDriverContext;

    BYTE                    ServerChallenge[8];

    union
    {
        PLWIO_SRV_SESSION   lruSession[SRV_LRU_CAPACITY];
        PLWIO_SRV_SESSION_2 lruSession2[SRV_LRU_CAPACITY];
    };

    PLWRTL_RB_TREE          pSessionCollection;
    ULONG64                 ullSessionCount;

    ULONG64                 ullNextAvailableAsyncId;

    PLWRTL_RB_TREE          pAsyncStateCollection;

    PSRV_LEASE_TABLE        LeaseTable;

    // Immutable.
    ULONG                   ulIdleTimeoutSeconds;

    // The following terminal mutex protects the count below it.
    pthread_mutex_t         mutexIdleTimeoutDisable;
    pthread_mutex_t*        pMutexIdleTimeoutDisable;
    LONG                    lIdleTimeoutDisableCount;

    PVOID                   pOEMConnection;
    ULONG                   ulOEMConnectionLength;

    PSRV_CREDITOR           pCreditor;

    PSRV_MPX_TRACKER        pMpxTracker;

    PLW_HASHMAP             pTidMap;
    USHORT                  NextTid;
    PLW_HASHMAP             pFidMap;
    USHORT                  NextFid;
} LWIO_SRV_CONNECTION;

typedef struct _SRV_FINDER_REPOSITORY
{
    LONG             refCount;

    pthread_mutex_t  mutex;
    pthread_mutex_t* pMutex;

    PLWRTL_RB_TREE   pSearchSpaceCollection;

    USHORT           usNextSearchId;

} SRV_FINDER_REPOSITORY, *PSRV_FINDER_REPOSITORY;

typedef struct _SRV_SEARCH_SPACE
{
    LONG             refCount;

    pthread_mutex_t  mutex;
    pthread_mutex_t* pMutex;

    USHORT           usSearchId;

    IO_FILE_HANDLE   hFile;
    PWSTR            pwszSearchPattern;
    SMB_FILE_ATTRIBUTES usSearchAttrs;
    ULONG            ulSearchStorageType;
    PBYTE            pFileInfo;
    PBYTE            pFileInfoCursor;
    USHORT           usFileInfoLen;
    SMB_INFO_LEVEL   infoLevel;
    BOOLEAN          bUseLongFilenames;

} SRV_SEARCH_SPACE, *PSRV_SEARCH_SPACE;

typedef struct _SRV_TIMER_REQUEST* PSRV_TIMER_REQUEST;

typedef VOID (*PFN_SRV_TIMER_CALLBACK)(
                    PSRV_TIMER_REQUEST pTimerRequest,
                    PVOID              pUserData
                    );

typedef struct _SMB_FS_VOLUME_INFO_HEADER
{
    LONG64  llVolumeCreationTime;
    ULONG   ulVolumeSerialNumber;
    ULONG   ulVolumeLabelLength;
    BOOLEAN bSupportsObjects;
    UCHAR   pad;
    WCHAR   wszVolumeLabel[];

} __attribute__((__packed__)) SMB_FS_VOLUME_INFO_HEADER,
                             *PSMB_FS_VOLUME_INFO_HEADER;

typedef struct _SMB_FS_ATTRIBUTE_INFO_HEADER
{
    ULONG ulFSAttributes;
    LONG  lMaxFilenameLen;
    ULONG ulFileSystemNameLen;
    WCHAR wszFileSystemName[];
} __attribute__((__packed__)) SMB_FS_ATTRIBUTE_INFO_HEADER,
                             *PSMB_FS_ATTRIBUTE_INFO_HEADER;

typedef struct _SMB_FS_CONTROL_INFO
{
    LONG64 llFreeSpaceStartFiltering;    // must be ignored
    LONG64 llFreeSpaceThreshold;         // must be ignored
    LONG64 llFreeSpaceStopFiltering;     // must be ignored
    LONG64 llDefaultQuotaThreshold;
    LONG64 llDefaultQuotaLimit;
    FILE_VC_FLAGS FileSystemControlFlags;
    BYTE Pad[4];                        // Windows pads to 48 bytes
    
} __attribute__((__packed__)) SMB_FS_CONTROL_INFO,
                             *PSMB_FS_CONTROL_INFO;

typedef struct _SMB_FS_DEVICE_INFO
{
    ULONG   ulDeviceType;
    ULONG   ulCharacteristics;

} __attribute__((__packed__)) SMB_FS_DEVICE_INFO,
                             *PSMB_FS_DEVICE_INFO;

typedef struct _SMB1_FS_VOLUME_INFO_HEADER
{
    ULONG   ulVolumeSerialNumber;
    UCHAR   ucNumLabelChars;
    WCHAR   wszVolumeLabel[];

} __attribute__((__packed__)) SMB1_FS_VOLUME_INFO_HEADER,
                             *PSMB1_FS_VOLUME_INFO_HEADER;

typedef struct _SMB_FS_FULL_SIZE_INFO
{
    ULONG64 ullTotalAllocationUnits;
    ULONG64 ullCallerAvailableAllocationUnits;
    ULONG64 ullActualAvailableAllocationUnits;
    ULONG   ulSectorsPerAllocationUnit;
    ULONG   ulBytesPerSector;

} __attribute__((__packed__)) SMB_FS_FULL_SIZE_INFO,
                             *PSMB_FS_FULL_INFO;

typedef struct _SMB_FS_SIZE_INFO
{
    LONG64 llTotalAllocationUnits;
    LONG64 llAvailableAllocationUnits;
    ULONG  ulSectorsPerAllocationUnit;
    ULONG  ulBytesPerSector;

} __attribute__((__packed__)) SMB_FS_SIZE_INFO,
                             *PSMB_FS_SIZE_INFO;

typedef struct _SMB_FS_OBJECTID_INFO {
    UCHAR ObjectId[16];
    UCHAR ExtendedInfo[48];
} __attribute__((__packed__)) SMB_FS_OBJECTID_INFO,
                             *PSMB_FS_OBJECTID_INFO;

typedef struct _SMB_FILE_INTERNAL_INFO
{
    ULONG64 ullIndex;

} __attribute__((__packed__)) SMB_FILE_INTERNAL_INFO,
                             *PSMB_FILE_INTERNAL_INFO;

typedef struct _SMB_FILE_EA_INFORMATION
{
    ULONG ulEaSize;

} __attribute__((__packed__)) SMB_FILE_EA_INFORMATION,
                             *PSMB_FILE_EA_INFORMATION;

typedef struct _SRV_EXEC_CONTEXT SRV_EXEC_CONTEXT, *PSRV_EXEC_CONTEXT;

typedef VOID (*PFN_SRV_PROTOCOL_FREE_EXEC_CONTEXT)(
                        PSRV_EXEC_CONTEXT pContext,
                        PVOID pProtocolContext
                        );

struct _SRV_EXEC_CONTEXT
{
    LONG                               refCount;

    pthread_mutex_t                    execMutex;
    pthread_mutex_t*                   pExecMutex;

    IO_ASYNC_CONTROL_BLOCK             acb;
    PIO_ASYNC_CONTROL_BLOCK            pAcb;

    IO_STATUS_BLOCK                    ioStatusBlock;

    PLW_WORK_ITEM                      pWorkItem;

    PLWIO_SRV_CONNECTION               pConnection;
    PSMB_PACKET                        pSmbRequest;

    PVOID                              pProtocolContext;
    PFN_SRV_PROTOCOL_FREE_EXEC_CONTEXT pfnFreeContext;

    PSMB_PACKET                        pSmbResponse;

    PSMB_PACKET                        pInterimResponse;

    BOOLEAN                            bInternal;
    BOOLEAN                            bInline;
    BOOLEAN                            bInterimSent;

    ULONG64                            ullAsyncId;
    USHORT                             usCreditsGranted;

    PSRV_STAT_INFO                     pStatInfo;

    PSRV_LOG_CONTEXT                   pLogContext;

    SRV_MPX_TRACKING_STATE             trackingState;

};

typedef struct _SRV_ELEMENTS_STATISTICS
{
    LONG64 llNumConnections;
    LONG64 llMaxNumConnections;

    LONG64 llNumSessions;
    LONG64 llMaxNumSessions;

    LONG64 llNumTreeConnects;
    LONG64 llMaxNumTreeConnects;

    LONG64 llNumOpenFiles;
    LONG64 llMaxNumOpenFiles;

} SRV_ELEMENTS_STATISTICS, *PSRV_ELEMENTS_STATISTICS;

typedef struct _SRV_OPLOCK
{
    LW_LIST_ENTRY               LeaseRecordEntry;
    PSRV_LEASE_RECORD           pLeaseRecord;
    LONG                        refCount;
    PFN_SRV_CANCEL_OPLOCK       pfnCancelOplock;
    PFN_SRV_FREE_OPLOCK         pfnFreeOplock;
    PFN_SRV_REPARENT_OPLOCK     pfnReparentOplock;
    PFN_SRV_GET_OPLOCK_LEVEL    pfnGetOplockLevel;
} SRV_OPLOCK;

typedef struct _SRV_DURABLE_ENTRY
{
    struct _SRV_DURABLE_TABLE* pTable;
    // Links entry into global hash table.
    LW_HASHTABLE_NODE HashNode;
    // Persistent file ID.
    ULONG64 DurableId;
    // Client Lease Key for verification in a reconnect
    GUID ClientLeaseKey;
    PGUID pClientLeaseKey;
    // File handle.  Set when handle is orphaned.
    IO_FILE_HANDLE FileHandle;
    // Immutable open state.  Set when handle is created.
    LWIO_SRV_OPEN_STATE_2 OpenState;
    // Oplock Handle.  Set when durable handle is orphaned.
    HANDLE hOplock;
    // Srv file object. Set when file is connected to a client.
    PLWIO_SRV_FILE_2 pSrvFile;
    // Original owner of durable open
    PACCESS_TOKEN pToken;
    // Timer to run down handle when orphaned
    PSRV_TIMER_REQUEST pReclaimTimer;
    // Control blocks for closing orphaned handle
    IO_ASYNC_CONTROL_BLOCK CloseAcb;
    IO_STATUS_BLOCK CloseStatus;
    // Ref count
    // +1 when present in global table
    // +1 when referenced by a srv file object or oplock state
    // +1 when a timer is scheduled
    LONG RefCount;
    // If true, handle is eligible for durable handle reconnect.
    BOOLEAN bValid;
} SRV_DURABLE_ENTRY;

typedef struct _SRV_DURABLE_TABLE
{
    PLW_HASHTABLE pTable;
    pthread_mutex_t Mutex;
    pthread_cond_t Condition;
    unsigned bDestroyMutex:1;
    unsigned bDestroyCondition:1;
    unsigned bShuttingDown:1;
} SRV_DURABLE_TABLE, *PSRV_DURABLE_TABLE;

typedef struct _SRV_LEASE_TABLES
{
    PLW_HASHTABLE pTable;
    pthread_mutex_t Mutex;
    pthread_cond_t Condition;
    unsigned bDestroyMutex:1;
    unsigned bDestroyCondition:1;
    unsigned bShuttingDown:1;
} SRV_LEASE_TABLES, *PSRV_LEASE_TABLES;

typedef struct _SRV_LEASE_RECORD
{
    PSRV_LEASE_TABLE pLeaseTable;
    GUID ClientLeaseKey;
    GUID FileSystemLeaseKey;
    IO_LEASE_STATE LeaseState;
    LONG RefCount;
    pthread_mutex_t Mutex;
    pthread_mutex_t* pMutex;
    LW_LIST_LINKS OplockList;
    LW_LIST_LINKS IterList;
} SRV_LEASE_RECORD;

typedef struct _SRV_LEASE_RECORD_ITERATOR
{
    LW_LIST_LINKS LeaseRecordEntry;
    PSRV_LEASE_RECORD pLeaseRecord;
    PLW_LIST_ENTRY pNextEntry;
    HANDLE hCurOplock;
} SRV_LEASE_RECORD_ITERATOR, *PSRV_LEASE_RECORD_ITERATOR;

typedef struct _SRV_SESSION2_TABLE
{
    PLW_HASHTABLE pTable;
    pthread_mutex_t Mutex;
    unsigned bDestroyMutex:1;
} SRV_SESSION2_TABLE, *PSRV_SESSION2_TABLE;

typedef struct _SRV_PROCESS_INFO_STATE
{
    PBYTE          pData;
    ULONG          ulOutputBufferLen;
    ULONG          ulDataLen;
    ULONG          ulActualDataLen;

    IO_FILE_HANDLE hFile;

    USHORT         usInfoClass;
} SRV_PROCESS_INFO_STATE, *PSRV_PROCESS_INFO_STATE;

typedef struct _GET_INFO_CLASS_DISPATCH_ENTRY
    GET_INFO_CLASS_DISPATCH_ENTRY, *PGET_INFO_CLASS_DISPATCH_ENTRY;

typedef NTSTATUS (GET_INFO_CLASS_GET_FUNC)(
    IN PSRV_EXEC_CONTEXT pExecContext,
    IN PSRV_PROCESS_INFO_STATE pInfoState,
    IN PGET_INFO_CLASS_DISPATCH_ENTRY pInfoEntry
    );
typedef GET_INFO_CLASS_GET_FUNC *PGET_INFO_CLASS_GET_FUNC;

typedef NTSTATUS (GET_INFO_CLASS_MARSHAL_FUNC)(
    IN PSRV_EXEC_CONTEXT pExecContext,
    IN PSRV_PROCESS_INFO_STATE pInfoState,
    IN PGET_INFO_CLASS_DISPATCH_ENTRY pInfoEntry,
    IN OUT PBYTE pOutBuffer,
    IN OUT ULONG ulBytesAvailable,
    IN OUT PULONG pulBytesUsed
    );
typedef GET_INFO_CLASS_MARSHAL_FUNC *PGET_INFO_CLASS_MARSHAL_FUNC;

struct _GET_INFO_CLASS_DISPATCH_ENTRY
{
    PGET_INFO_CLASS_GET_FUNC      GetHandler;
    PGET_INFO_CLASS_MARSHAL_FUNC  MarshalHandler;
    ULONG                         InfoClass;
    size_t                        ProtoStructSize;
    size_t                        IOStructSize;
};

static
inline
NTSTATUS
SrvReparentOplock(
    HANDLE hOplock,
    PLWIO_SRV_FILE_2 pFile,
    PSRV_DURABLE_ENTRY pEntry
    )
{
    PSRV_OPLOCK pOplock = hOplock;

    return pOplock->pfnReparentOplock(hOplock, pFile, pEntry);
}

static
inline
VOID
SrvGetOplockLevel(
    HANDLE hOplock,
    PUCHAR pOplockLevel,
    PULONG pLeaseState)
{
    PSRV_OPLOCK pOplock = hOplock;

    pOplock->pfnGetOplockLevel(pOplock, pOplockLevel, pLeaseState);
}

static
inline
VOID
SrvCancelOplock(
    HANDLE hOplock
    )
{
    PSRV_OPLOCK pOplock = hOplock;

    pOplock->pfnCancelOplock(pOplock);
}

static
inline
PSRV_OPLOCK
SrvAcquireOplock(
    HANDLE hOplock
    )
{
    PSRV_OPLOCK pOplock = hOplock;

    InterlockedIncrement(&pOplock->refCount);

    return pOplock;
}

static
inline
VOID
SrvReleaseOplock(
    HANDLE hOplock
    )
{
    PSRV_OPLOCK pOplock = hOplock;

    if (InterlockedDecrement(&pOplock->refCount) == 0)
    {
        pOplock->pfnFreeOplock(pOplock);
    }
}

NTSTATUS
SrvElementsInit(
    IN PLW_THREAD_POOL ThreadPool,
    IN LW_WORK_ITEM_FUNCTION WorkItemFunction
    );

NTSTATUS
SrvTimerPostRequest(
    IN  LONG64                 llExpiry,
    IN  PVOID                  pUserData,
    IN  PFN_SRV_TIMER_CALLBACK pfnTimerExpiredCB,
    OUT PSRV_TIMER_REQUEST*    ppTimerRequest
    );

NTSTATUS
SrvTimerCancelRequest(
    IN  PSRV_TIMER_REQUEST pTimerRequest,
    OUT PVOID*             ppUserData
    );

NTSTATUS
SrvTimerRelease(
    IN  PSRV_TIMER_REQUEST *ppTimerRequest
    );

BOOLEAN
SrvGssNegotiateIsComplete(
    HANDLE hGssNegotiate
    );

NTSTATUS
SrvGssGetSessionDetails(
    HANDLE hGssNegotiate,
    PBYTE* ppSessionKey,
    PULONG pulSessionKeyLength,
    PSTR* ppszClientPrincipalName,
    LW_MAP_SECURITY_GSS_CONTEXT* pContextHandle
    );

NTSTATUS
SrvGssBeginNegotiate(
    PHANDLE phGssNegotiate
    );

NTSTATUS
SrvGssNegotiate(
    HANDLE  hGssResume,
    PBYTE   pSecurityInputBlob,
    ULONG   ulSecurityInputBlobLen,
    PBYTE*  ppSecurityOutputBlob,
    ULONG*  pulSecurityOutputBloblen
    );

VOID
SrvGssEndNegotiate(
    HANDLE hGssNegotiate
    );

NTSTATUS
SrvGssCollapseLogonFailureStatus(
    NTSTATUS Status
    );

NTSTATUS
SrvGssNegHints(
    PBYTE *ppNegHints,
    ULONG *pulNegHintsLength
    );

ULONG64
SrvAsyncStateBuildId(
    ULONG  ulPid,
    USHORT usMid
    );

NTSTATUS
SrvAsyncStateCreate(
    ULONG64                         ullAsyncId,
    USHORT                          usCommand,
    HANDLE                          hAsyncState,
    PFN_LWIO_SRV_CANCEL_ASYNC_STATE pfnCancelAsyncState,
    PFN_LWIO_SRV_FREE_ASYNC_STATE   pfnFreeAsyncState,
    PLWIO_ASYNC_STATE*              ppAsyncState
    );

VOID
SrvAsyncStateCancel(
    PLWIO_ASYNC_STATE pAsyncState
    );

PLWIO_ASYNC_STATE
SrvAsyncStateAcquire(
    PLWIO_ASYNC_STATE pAsyncState
    );

VOID
SrvAsyncStateRelease(
    PLWIO_ASYNC_STATE pAsyncState
    );

NTSTATUS
SrvConnectionCreate(
    PLWIO_SRV_SOCKET                pSocket,
    HANDLE                          hPacketAllocator,
    SRV_SHARES_HANDLE hShares,
    PSRV_PROPERTIES                 pServerProperties,
    PSRV_CONNECTION_SOCKET_DISPATCH pSocketDispatch,
    PLWIO_SRV_CONNECTION*           ppConnection
    );

static
inline
SMB_PROTOCOL_VERSION
SrvConnectionGetProtocolVersion(
    PLWIO_SRV_CONNECTION pConnection
    )
{
    return pConnection->protocolVer;
}

SMB_PROTOCOL_VERSION
SrvConnectionGetProtocolVersion_inlock(
    PLWIO_SRV_CONNECTION pConnection
    );

NTSTATUS
SrvConnectionSetProtocolVersion(
    IN PLWIO_SRV_CONNECTION pConnection,
    IN SMB_PROTOCOL_VERSION Version,
    IN SMB_PROTOCOL_DIALECT Dialect
    );

NTSTATUS
SrvConnectionSetProtocolVersion_inlock(
    IN PLWIO_SRV_CONNECTION pConnection,
    IN SMB_PROTOCOL_VERSION protoVer,
    IN SMB_PROTOCOL_DIALECT Dialect
    );

NTSTATUS
SrvConnectionCreateSession(
    PLWIO_SRV_CONNECTION pConnection,
    PLWIO_SRV_SESSION* ppSession
    );

NTSTATUS
SrvConnection2CreateSession(
    PLWIO_SRV_CONNECTION pConnection,
    PLWIO_SRV_SESSION_2* ppSession
    );

NTSTATUS
SrvConnectionFindSession_inlock(
    PLWIO_SRV_CONNECTION pConnection,
    USHORT               uid,
    PLWIO_SRV_SESSION*   ppSession
    );

NTSTATUS
SrvConnectionFindSession(
    PLWIO_SRV_CONNECTION pConnection,
    USHORT               uid,
    PLWIO_SRV_SESSION*   ppSession
    );

NTSTATUS
SrvConnection2FindSession_inlock(
    PLWIO_SRV_CONNECTION pConnection,
    ULONG64              ullUid,
    PLWIO_SRV_SESSION_2* ppSession
    );

NTSTATUS
SrvConnection2FindSession(
    PLWIO_SRV_CONNECTION pConnection,
    ULONG64              ullUid,
    PLWIO_SRV_SESSION_2* ppSession
    );

NTSTATUS
SrvConnectionGetSessionCount(
    PLWIO_SRV_CONNECTION pConnection,
    PWSTR                pwszUsername,
    PULONG64             pullSessionCount
    );

NTSTATUS
SrvConnection2GetSessionCount(
    PLWIO_SRV_CONNECTION pConnection,
    PWSTR                pwszUsername,
    PULONG64             pullSessionCount
    );

NTSTATUS
SrvConnectionGetConnectionCount(
    PLWIO_SRV_CONNECTION pConnection,
    PWSTR                pwszShareName,
    PULONG               pulConnectionCount
    );

NTSTATUS
SrvConnectionGetConnectionCount2(
    PLWIO_SRV_CONNECTION pConnection,
    PWSTR                pwszShareName,
    PULONG               pulConnectionCount
    );

NTSTATUS
SrvConnection2CreateAsyncState(
    PLWIO_SRV_CONNECTION            pConnection,
    USHORT                          usCommand,
    ULONG64                         ullCommandSequence,
    PFN_LWIO_SRV_CANCEL_ASYNC_STATE pfnCancelAsyncState,
    PFN_LWIO_SRV_FREE_ASYNC_STATE   pfnFreeAsyncState,
    PLWIO_ASYNC_STATE*              ppAsyncState
    );

NTSTATUS
SrvConnection2FindAsyncState(
    PLWIO_SRV_CONNECTION pConnection,
    ULONG64              ullAsyncId,
    PLWIO_ASYNC_STATE*   ppAsyncState
    );


NTSTATUS
SrvConnection2FindAsyncStateBySequence(
    PLWIO_SRV_CONNECTION pConnection,
    ULONG64              ullCommandSequence,
    PLWIO_ASYNC_STATE*   ppAsyncState
    );


VOID
SrvConnection2RemoveAsyncState(
    PLWIO_SRV_CONNECTION pConnection,
    ULONG64              ullAsyncId
    );

NTSTATUS
SrvConnectionGetNamedPipeClientAddress(
    PLWIO_SRV_CONNECTION pConnection,
    PIO_ECP_LIST        pEcpList
    );

NTSTATUS
SrvConnectionDeleteSessions(
    PLWIO_SRV_CONNECTION pConnection,
    PWSTR                pwszUsername
    );

LWIO_SRV_CONN_STATE
SrvConnectionGetState(
    PLWIO_SRV_CONNECTION pConnection
    );

BOOLEAN
SrvConnectionIsInvalid(
    PLWIO_SRV_CONNECTION pConnection
    );

PLWIO_SRV_CONNECTION
SrvConnectionAcquire(
    PLWIO_SRV_CONNECTION pConnection
    );

VOID
SrvConnectionRelease(
    PLWIO_SRV_CONNECTION pConnection
    );

NTSTATUS
SrvConnectionRemoveSession(
    PLWIO_SRV_CONNECTION pConnection,
    PLWIO_SRV_SESSION pSession
    );

NTSTATUS
SrvConnection2RemoveSession(
    PLWIO_SRV_CONNECTION pConnection,
    PLWIO_SRV_SESSION_2 pSession
    );

VOID
SrvConnectionSetInvalid(
    PLWIO_SRV_CONNECTION pConnection
    );

VOID
SrvConnectionSetInvalidAsync_inlock(
    PLWIO_SRV_CONNECTION pConnection,
    ULONG64 AsyncID 
    );

BOOLEAN
SrvConnectionSetInvalidIfNoSessions(
    PLWIO_SRV_CONNECTION pConnection
    );

VOID
SrvConnectionSetState(
    PLWIO_SRV_CONNECTION pConnection,
    LWIO_SRV_CONN_STATE  connState
    );

NTSTATUS
SrvConnectionSetSigningKeyIfUnset(
    PLWIO_SRV_CONNECTION pConnection,
    PBYTE                pSessionKey,
    ULONG                ulSessionKeyLength);

BOOLEAN
SrvConnectionShouldSign(
    PLWIO_SRV_CONNECTION pConnection
    );

VOID
SrvConnectionResetIdleTimeout(
    PLWIO_SRV_CONNECTION pConnection
    );

VOID
SrvConnectionIncrementIdleDisableCount(
    PLWIO_SRV_CONNECTION pConnection
    );

VOID
SrvConnectionDecrementIdleDisableCount(
    PLWIO_SRV_CONNECTION pConnection
    );

NTSTATUS
SrvConnectionAcquireTid(
    PLWIO_SRV_CONNECTION pConnection,
    PUSHORT pTid
    );

VOID
SrvConnectionReleaseTid(
    PLWIO_SRV_CONNECTION pConnection,
    USHORT Tid
    );

NTSTATUS
SrvConnectionAcquireFid(
    PLWIO_SRV_CONNECTION pConnection,
    PUSHORT pFid
    );

VOID
SrvConnectionReleaseFid(
    PLWIO_SRV_CONNECTION pConnection,
    USHORT Fid
    );

NTSTATUS
SrvSessionCreate(
    PLWIO_SRV_CONNECTION pConnection,
    USHORT            uid,
    PLWIO_SRV_SESSION* ppSession
    );

NTSTATUS
SrvSessionFindTree(
    PLWIO_SRV_SESSION pSession,
    USHORT           tid,
    PLWIO_SRV_TREE*   ppTree
    );

NTSTATUS
SrvSessionRemoveTree(
    PLWIO_SRV_SESSION pSession,
    PLWIO_SRV_TREE pTree
    );

NTSTATUS
SrvSessionCreateTree(
    PLWIO_SRV_SESSION pSession,
    PSRV_SHARE_INFO   pShareInfo,
    PLWIO_SRV_TREE*   ppTree
    );

NTSTATUS
SrvSessionSetPrincipalName(
    PLWIO_SRV_SESSION pSession,
    PCSTR             pszClientPrincipal
    );

VOID
SrvSessionSetNtName(
    IN OUT PLWIO_SRV_SESSION pSession,
    IN OUT PWSTR* pDomain,
    IN OUT PWSTR* pUser
    );

BOOLEAN
SrvSessionIsMatchPrincipal(
    PLWIO_SRV_SESSION pSession,
    PCWSTR            pwszClientPrincipal
    );

NTSTATUS
SrvSessionGetPrincipalName(
    PLWIO_SRV_SESSION pSession,
    PWSTR*            ppwszClientPrincipal
    );

VOID
SrvSessionSetUserFlags(
    PLWIO_SRV_SESSION pSession,
    ULONG Flags
    );

NTSTATUS
SrvSessionGetFileCount(
    PLWIO_SRV_SESSION pSession,
    PULONG64          pullFileCount
    );

NTSTATUS
SrvSessionGetNamedPipeSessionKey(
    PLWIO_SRV_SESSION pSession,
    PIO_ECP_LIST      pEcpList
    );

PLWIO_SRV_SESSION
SrvSessionAcquire(
    PLWIO_SRV_SESSION pSession
    );

VOID
SrvSessionRelease(
    PLWIO_SRV_SESSION pSession
    );

VOID
SrvSessionRundown(
    PLWIO_SRV_SESSION pSession
    );

NTSTATUS
SrvSession2Create(
    PLWIO_SRV_CONNECTION pConnection,
    PLWIO_SRV_SESSION_2* ppSession
    );

NTSTATUS
SrvSession2FindTree(
    PLWIO_SRV_SESSION_2 pSession,
    ULONG               ulTid,
    PLWIO_SRV_TREE_2*   ppTree
    );

NTSTATUS
SrvSession2RemoveTree(
    PLWIO_SRV_SESSION_2 pSession,
    PLWIO_SRV_TREE_2 pTree
    );

NTSTATUS
SrvSession2CreateTree(
    PLWIO_SRV_SESSION_2 pSession,
    PSRV_SHARE_INFO     pShareInfo,
    PLWIO_SRV_TREE_2*   ppTree
    );

NTSTATUS
SrvSession2SetPrincipalName(
    PLWIO_SRV_SESSION_2 pSession,
    PCSTR               pszClientPrincipal
    );

VOID
SrvSession2SetNtName(
    IN OUT PLWIO_SRV_SESSION_2 pSession,
    IN OUT PWSTR* pDomain,
    IN OUT PWSTR* pUser
    );

BOOLEAN
SrvSession2IsMatchPrincipal(
    PLWIO_SRV_SESSION_2 pSession,
    PCWSTR              pwszClientPrincipal
    );

NTSTATUS
SrvSession2GetPrincipalName(
    PLWIO_SRV_SESSION_2 pSession,
    PWSTR*              ppwszClientPrincipal
    );

NTSTATUS
SrvSession2GetNamedPipeSessionKey(
    PLWIO_SRV_SESSION_2 pSession,
    PIO_ECP_LIST        pEcpList
    );

VOID
SrvSession2SetUserFlags(
    PLWIO_SRV_SESSION_2 pSession,
    ULONG Flags
    );

NTSTATUS
SrvSession2GetFileCount(
    PLWIO_SRV_SESSION_2 pSession,
    PULONG64            pullFileCount
    );

PLWIO_SRV_SESSION_2
SrvSession2Acquire_impl(
    PLWIO_SRV_SESSION_2 pSession,
    PCSTR func,
    LONG line
    );

#define SrvSession2Acquire(session) \
    SrvSession2Acquire_impl(session, __func__, __LINE__)

VOID
SrvSession2Release_impl(
    PLWIO_SRV_SESSION_2 pSession,
    PCSTR func,
    LONG line
    );

#define SrvSession2Release(session) \
    SrvSession2Release_impl(session, __func__, __LINE__)

VOID
SrvSession2Rundown(
    PLWIO_SRV_SESSION_2 pSession
    );

BOOLEAN
SrvSession2IsRundown(
    PLWIO_SRV_SESSION_2 pSession
    );

NTSTATUS
SrvTreeCreate(
    PLWIO_SRV_SESSION pSession,
    USHORT            tid,
    PSRV_SHARE_INFO   pShareInfo,
    PLWIO_SRV_TREE*   ppTree
    );

NTSTATUS
SrvTreeFindFile(
    PLWIO_SRV_TREE  pTree,
    USHORT         fid,
    PLWIO_SRV_FILE* ppFile
    );

NTSTATUS
SrvTreeCreateFile(
    PLWIO_SRV_TREE           pTree,
    PWSTR                   pwszFilename,
    PIO_FILE_HANDLE         phFile,
    PIO_FILE_NAME*          ppFilename,
    ACCESS_MASK             desiredAccess,
    LONG64                  allocationSize,
    FILE_ATTRIBUTES         fileAttributes,
    FILE_SHARE_FLAGS        shareAccess,
    FILE_CREATE_DISPOSITION createDisposition,
    FILE_CREATE_OPTIONS     createOptions,
    LONG64                  SnapshotTime,
    PLWIO_SRV_FILE*          ppFile
    );

NTSTATUS
SrvTreeRemoveFile(
    PLWIO_SRV_TREE pTree,
    PLWIO_SRV_FILE pFile
    );

NTSTATUS
SrvTreeAddAsyncState(
    PLWIO_SRV_TREE    pTree,
    PLWIO_ASYNC_STATE pAsyncState
    );

NTSTATUS
SrvTreeFindAsyncState(
    PLWIO_SRV_TREE     pTree,
    ULONG64            ullAsyncId,
    PLWIO_ASYNC_STATE* ppAsyncState
    );

VOID
SrvTreeRemoveAsyncState(
    PLWIO_SRV_TREE pTree,
    ULONG64        ullAsyncId
    );

BOOLEAN
SrvTreeIsNamedPipe(
    PLWIO_SRV_TREE pTree
    );

NTSTATUS
SrvGetTreeRelativePath(
    PWSTR  pwszOriginalPath,
    PWSTR* ppwszSpecificPath
    );

PLWIO_SRV_TREE
SrvTreeAcquire(
    PLWIO_SRV_TREE pTree
    );

VOID
SrvTreeRelease(
    PLWIO_SRV_TREE pTree
    );

VOID
SrvTreeRundown(
    PLWIO_SRV_TREE pTree
    );

NTSTATUS
SrvTree2Create(
    PLWIO_SRV_SESSION_2 pSession,
    ULONG             ulTid,
    PSRV_SHARE_INFO   pShareInfo,
    PLWIO_SRV_TREE_2* ppTree
    );

NTSTATUS
SrvTree2FindFile(
    PLWIO_SRV_TREE_2  pTree,
    PSMB2_FID         pFid,
    PLWIO_SRV_FILE_2* ppFile
    );

NTSTATUS
SrvTree2CreateFile(
    PLWIO_SRV_TREE_2        pTree,
    PWSTR                   pwszFilename,
    PIO_FILE_HANDLE         phFile,
    PIO_FILE_NAME*          ppFilename,
    ACCESS_MASK             desiredAccess,
    LONG64                  allocationSize,
    FILE_ATTRIBUTES         fileAttributes,
    FILE_SHARE_FLAGS        shareAccess,
    FILE_CREATE_DISPOSITION createDisposition,
    FILE_CREATE_OPTIONS     createOptions,
    LONG64                  SnapshotTime,
    PLWIO_SRV_FILE_2*       ppFile
    );

NTSTATUS
SrvTree2RemoveFile(
    PLWIO_SRV_TREE_2 pTree,
    PLWIO_SRV_FILE_2 pFile
    );

BOOLEAN
SrvTree2IsNamedPipe(
    PLWIO_SRV_TREE_2 pTree
    );

PLWIO_SRV_TREE_2
SrvTree2Acquire(
    PLWIO_SRV_TREE_2 pTree
    );

VOID
SrvTree2Release(
    PLWIO_SRV_TREE_2 pTree
    );

VOID
SrvTree2Rundown(
    PLWIO_SRV_TREE_2 pTree
    );

BOOLEAN
SrvIoSecurityContextUserEqual(
    IN PIO_CREATE_SECURITY_CONTEXT pSecurityContext1,
    IN PIO_CREATE_SECURITY_CONTEXT pSecurityContext2
    );


NTSTATUS
SrvIoSecCreateSecurityContextFromGssContext(
    OUT PIO_CREATE_SECURITY_CONTEXT* SecurityContext,
    OUT PBOOLEAN pMappedToGuest,
    IN LW_MAP_SECURITY_GSS_CONTEXT hGssContext,
    IN PCSTR pszUsername
    );

NTSTATUS
SrvIoSecCreateSecurityContextFromNtlmLogon(
    OUT PIO_CREATE_SECURITY_CONTEXT* ppSecurityContext,
    OUT PBOOLEAN pbLoggedInAsGuest,
    OUT PSTR* ppszUsername,
    OUT PVOID* ppSessionKey,
    OUT PULONG pulSessionKeyLength,
    IN PLW_MAP_SECURITY_NTLM_LOGON_INFO pNtlmLogonInfo
    );

NTSTATUS
SrvIoGetNtNameFromIoSecurityContext(
    IN PIO_CREATE_SECURITY_CONTEXT pContext,
    OUT PWSTR* ppDomain,
    OUT PWSTR* ppUser
    );

NTSTATUS
SrvIoCreateFile(
    PSRV_EXEC_CONTEXT             pExecContext,            /* IN OPTIONAL     */
    PSRV_SHARE_INFO               pShareInfo,              /* IN              */
    PIO_FILE_HANDLE               pFileHandle,             /*    OUT          */
    PIO_ASYNC_CONTROL_BLOCK       pAsyncControlBlock,      /* IN OUT OPTIONAL */
    PIO_STATUS_BLOCK              pIoStatusBlock,          /*    OUT          */
    PIO_CREATE_SECURITY_CONTEXT   pSecurityContext,        /* IN              */
    PIO_FILE_NAME                 pFileName,               /* IN              */
    PSECURITY_DESCRIPTOR_RELATIVE pSecurityDescriptor,     /* IN     OPTIONAL */
    PVOID                         pSecurityQOS,            /* IN     OPTIONAL */
    ACCESS_MASK                   DesiredAccess,           /* IN              */
    LONG64                        AllocationSize,          /* IN     OPTIONAL */
    FILE_ATTRIBUTES               FileAttributes,          /* IN              */
    FILE_SHARE_FLAGS              ShareAccess,             /* IN              */
    FILE_CREATE_DISPOSITION       CreateDisposition,       /* IN              */
    FILE_CREATE_OPTIONS           CreateOptions,           /* IN              */
    PVOID                         pEaBuffer,               /* IN     OPTIONAL */
    ULONG                         EaLength,                /* IN              */
    PLONG64                       pSnapshotTime,           /* IN              */
    PIO_ECP_LIST*                 ppEcpList                /* IN OUT          */
    );

NTSTATUS
SrvIoPrepareAbeEcpList(
    PIO_ECP_LIST pEcpList    /* IN */
    );

NTSTATUS
SrvFileCreate(
    PLWIO_SRV_TREE          pTree,
    USHORT                  fid,
    PWSTR                   pwszFilename,
    PIO_FILE_HANDLE         phFile,
    PIO_FILE_NAME*          ppFilename,
    ACCESS_MASK             desiredAccess,
    LONG64                  allocationSize,
    FILE_ATTRIBUTES         fileAttributes,
    FILE_SHARE_FLAGS        shareAccess,
    FILE_CREATE_DISPOSITION createDisposition,
    FILE_CREATE_OPTIONS     createOptions,
    LONG64                  SnapshotTime,
    PLWIO_SRV_FILE*         ppFile
    );

NTSTATUS
SrvFileSetOplock(
    PLWIO_SRV_FILE pFile,
    HANDLE         hOplock
    );

HANDLE
SrvFileRemoveOplock(
    PLWIO_SRV_FILE pFile
    );

VOID
SrvFileResetOplock(
    PLWIO_SRV_FILE pFile
    );

VOID
SrvFileSetOplockLevel(
    PLWIO_SRV_FILE pFile,
    UCHAR          ucOplockLevel
    );

UCHAR
SrvFileGetOplockLevel(
    PLWIO_SRV_FILE pFile
    );

VOID
SrvFileSetLastFailedLockOffset(
    PLWIO_SRV_FILE pFile,
    ULONG64        ullLastFailedLockOffset
    );

ULONG64
SrvFileGetLastFailedLockOffset(
    PLWIO_SRV_FILE pFile
    );

VOID
SrvFileRegisterLock(
    PLWIO_SRV_FILE pFile
    );

VOID
SrvFileRegisterUnlock(
    PLWIO_SRV_FILE pFile
    );

PLWIO_SRV_FILE
SrvFileAcquire(
    PLWIO_SRV_FILE pFile
    );

VOID
SrvFileRelease(
    PLWIO_SRV_FILE pFile
    );

VOID
SrvFileBlockIdleTimeout(
    PLWIO_SRV_FILE pFile
    );

VOID
SrvFileUnblockIdleTimeout(
    PLWIO_SRV_FILE pFile
    );

VOID
SrvFileRundown(
    PLWIO_SRV_FILE pFile
    );

BOOLEAN
SrvFileIsRundown(
    PLWIO_SRV_FILE pFile
    );

NTSTATUS
SrvFile2Create(
    PLWIO_SRV_TREE_2        pTree,
    PSMB2_FID               pFid,
    PWSTR                   pwszFilename,
    PIO_FILE_HANDLE         phFile,
    PIO_FILE_NAME*          ppFilename,
    ACCESS_MASK             desiredAccess,
    LONG64                  allocationSize,
    FILE_ATTRIBUTES         fileAttributes,
    FILE_SHARE_FLAGS        shareAccess,
    FILE_CREATE_DISPOSITION createDisposition,
    FILE_CREATE_OPTIONS     createOptions,
    LONG64                  SnapshotTime,
    PLWIO_SRV_FILE_2*       ppFile
    );

NTSTATUS
SrvFile2SetOplock(
    PLWIO_SRV_FILE_2    pFile,
    HANDLE              hOplock
    );

VOID
SrvFile2ResetOplock(
    PLWIO_SRV_FILE_2 pFile
    );

VOID
SrvFile2SetOplockLevel(
    PLWIO_SRV_FILE_2 pFile,
    UCHAR            ucOplockLevel
    );

UCHAR
SrvFile2GetOplockLevel(
    PLWIO_SRV_FILE_2 pFile
    );

VOID
SrvFile2SetClosing(
    PLWIO_SRV_FILE_2 pFile
    );

BOOLEAN
SrvFile2IsFileClosing(
    PLWIO_SRV_FILE_2 pFile
    );

VOID
SrvFile2RegisterLock(
    PLWIO_SRV_FILE_2 pFile
    );

VOID
SrvFile2RegisterUnlock(
    PLWIO_SRV_FILE_2 pFile
    );

PLWIO_SRV_FILE_2
SrvFile2Acquire_impl(
    PLWIO_SRV_FILE_2 pFile,
    PCSTR   func,
    LONG    line
    );

#define SrvFile2Acquire(file) SrvFile2Acquire_impl(file, __func__, __LINE__)


VOID
SrvFile2Release_impl(
    PLWIO_SRV_FILE_2 pFile,
    PCSTR   func,
    LONG    line
    );

#define SrvFile2Release(file)   SrvFile2Release_impl(file, __func__, __LINE__)


VOID
SrvFile2BlockIdleTimeout(
    PLWIO_SRV_FILE_2 pFile
    );

VOID
SrvFile2UnblockIdleTimeout(
    PLWIO_SRV_FILE_2 pFile
    );

VOID
SrvFile2Rundown(
    PLWIO_SRV_FILE_2 pFile
    );

BOOLEAN
SrvFile2IsRundown(
    PLWIO_SRV_FILE_2 pFile
    );

NTSTATUS
SrvFinderCreateRepository(
    OUT PHANDLE phFinderRepository
    );

NTSTATUS
SrvFinderBuildSearchPath(
    IN              PWSTR    pwszPath,
    IN              PWSTR    pwszSearchPattern,
       OUT          PWSTR*   ppwszFilesystemPath,
       OUT          PWSTR*   ppwszSearchPattern,
    IN OUT OPTIONAL PBOOLEAN pbPathHasWildCards
    );

NTSTATUS
SrvFinderCreateSearchSpace(
    IN  PSRV_EXEC_CONTEXT pExecContext,
    IN  IO_FILE_HANDLE  hRootFileHandle,
    IN  PSRV_SHARE_INFO pShareInfo,
    IN  PIO_CREATE_SECURITY_CONTEXT pIoSecurityContext,
    IN  HANDLE         hFinderRepository,
    IN  PWSTR          pwszFilesystemPath,
    IN  PWSTR          pwszSearchPattern,
    IN  PLONG64        pSnapshotTime,
    IN  SMB_FILE_ATTRIBUTES usSearchAttrs,
    IN  USHORT         usFlags,
    IN  ULONG          ulSearchStorageType,
    IN  SMB_INFO_LEVEL infoLevel,
    IN  BOOLEAN        bUseLongFilenames,
    IN  ACCESS_MASK    accessMask,
    OUT PHANDLE        phFinder,
    OUT PUSHORT        pusSearchId
    );

NTSTATUS
SrvFinderGetSearchSpace(
    IN  HANDLE  hFinderRepository,
    IN  USHORT  usSearchId,
    OUT PHANDLE phFinder
    );

VOID
SrvFinderReleaseSearchSpace(
    IN HANDLE hFinder
    );

NTSTATUS
SrvFinderCloseSearchSpace(
    IN HANDLE hFinderRepository,
    IN USHORT usSearchId
    );

VOID
SrvFinderCloseRepository(
    IN HANDLE hFinderRepository
    );

NTSTATUS
SrvBuildExecContext(
   IN  PLWIO_SRV_CONNECTION pConnection,
   IN  PSMB_PACKET          pSmbRequest,
   IN  BOOLEAN              bInternal,
   OUT PSRV_EXEC_CONTEXT*   ppContext
   );

BOOLEAN
SrvIsValidExecContext(
   IN PSRV_EXEC_CONTEXT pExecContext
   );

VOID
SrvReleaseExecContextHandle(
   IN HANDLE hExecContext
   );


PSRV_EXEC_CONTEXT
SrvAcquireExecContext_impl(
   PSRV_EXEC_CONTEXT pContext,
   PCSTR func,
   LONG line
   );

#define SrvAcquireExecContext(context)   \
    SrvAcquireExecContext_impl(context, __func__, __LINE__)

VOID
SrvReleaseExecContext_impl(
   IN PSRV_EXEC_CONTEXT pContext,
   PCSTR func,
   LONG line
   );

#define SrvReleaseExecContext(context)   \
    SrvReleaseExecContext_impl(context, __func__, __LINE__)

BOOLEAN
SrvMpxTrackerIsNtCancelPacket(
    PSMB_PACKET pPacket
    );

NTSTATUS
SrvMpxTrackerAddExecContext_inlock(
    PLWIO_SRV_CONNECTION pConnection,
    PSRV_EXEC_CONTEXT pContext
    );

VOID
SrvMpxTrackerSwapExecContext(
    PSRV_EXEC_CONTEXT pContext,
    PSRV_EXEC_CONTEXT pNewContext
    );

VOID
SrvMpxTrackerRemoveExecContext(
    PSRV_EXEC_CONTEXT pContext
    );

VOID
SrvMpxTrackerSetExecutingExecContext(
    PSRV_EXEC_CONTEXT pContext
    );

BOOLEAN
SrvMpxTrackerIsCancelledExecContext(
    PSRV_EXEC_CONTEXT pContext
    );

VOID
SrvMpxTrackerCancelExecContextById(
    PSRV_MPX_TRACKER pTracker,
    ULONG ulPid,
    USHORT usMid,
    USHORT usUid,
    USHORT usTid
    );

NTSTATUS
SrvElementsGetBootTime(
    PULONG64 pullBootTime
    );

BOOLEAN
SrvElementsGetShareNameEcpEnabled(
    VOID
    );

BOOLEAN
SrvElementsGetClientAddressEcpEnabled(
    VOID
    );

BOOLEAN
SrvElementsGetOEMSessionEcpEnabled(
    VOID
    );

NTSTATUS
SrvElementsGetStats(
    PSRV_ELEMENTS_STATISTICS pStats
    );

NTSTATUS
SrvElementsRegisterResource(
    PSRV_RESOURCE pResource,     /* IN OUT          */
    PULONG        pulResourceId  /* IN OUT OPTIONAL */
    );

NTSTATUS
SrvElementsFindResource(
    ULONG              ulResourceId,
    SRV_RESOURCE_TYPE  resourceType,
    PFN_ENUM_RESOURCES pfnEnumResourcesCB,
    PVOID              pUserData
    );

NTSTATUS
SrvElementsEnumResources(
    SRV_RESOURCE_TYPE  resourceType,
    PFN_ENUM_RESOURCES pfnEnumResourcesCB,
    PVOID              pUserData
    );

NTSTATUS
SrvElementsUnregisterResource(
    ULONG          ulResourceId, /* IN              */
    PSRV_RESOURCE* ppResource    /*    OUT OPTIONAL */
    );

NTSTATUS
SrvElementsResetStats(
    VOID
    );

NTSTATUS
SrvElementsShutdown(
    VOID
    );

NTSTATUS
SrvConnectionGetSessionCount(
    PLWIO_SRV_CONNECTION pConnection,
    PWSTR                pwszUsername,
    PULONG64             pullSessionCount
    );

NTSTATUS
SrvConnection2GetSessionCount(
    PLWIO_SRV_CONNECTION pConnection,
    PWSTR                pwszUsername,
    PULONG64             pullSessionCount
    );

// creditor.c

NTSTATUS
SrvCreditorUpdateCreditWindow(
    IN OUT PSRV_CREDITOR pCreditor,
    IN ULONG64 ullFirstSeq,
    IN USHORT usCreditCharge,
    IN USHORT usCreditsRequested,
    OUT PUSHORT pusCreditsGranted
    );

// durable.c

PSRV_DURABLE_TABLE
SrvGetDurableHandleTable(
    VOID
    );

NTSTATUS
SrvSmb2DurableInit(
    OUT PSRV_DURABLE_TABLE pTable
    );

VOID
SrvSmb2DurableShutdown(
    IN OUT PSRV_DURABLE_TABLE pTable
    );

NTSTATUS
SrvSmb2DurableCreate(
    IN PSRV_DURABLE_TABLE pTable,
    OUT PSRV_DURABLE_ENTRY* ppEntry,
    IN ULONG64 DurableId,
    IN PACCESS_TOKEN pToken,
    IN PLWIO_SRV_OPEN_STATE_2 pState,
    IN PLWIO_SRV_FILE_2 pSrvFile,
    IN OPTIONAL PGUID ClientLeaseKey
    );

VOID
SrvSmb2DurableClose(
    IN PSRV_DURABLE_TABLE pTable,
    IN PSRV_DURABLE_ENTRY pEntry,
    IN PLWIO_SRV_FILE_2 pSrvFile
    );

NTSTATUS
SrvSmb2DurableOrphan(
    IN PSRV_DURABLE_TABLE pTable,
    IN PSRV_DURABLE_ENTRY pEntry,
    IN IO_FILE_HANDLE FileHandle,
    IN OUT PHANDLE phOplock,
    IN ULONG Timeout
    );

NTSTATUS
SrvSmb2DurableReconnect(
    IN PSRV_DURABLE_TABLE pTable,
    IN ULONG64 DurableId,
    IN PACCESS_TOKEN pToken,
    IN PLWIO_SRV_FILE_2 pSrvFile,
    IN OPTIONAL PGUID ClientLeaseKey
    );

// lease.c

NTSTATUS
SrvLeaseInit(
    OUT PSRV_LEASE_TABLES pTables
    );

VOID
SrvLeaseShutdown(
    IN OUT PSRV_LEASE_TABLES pTables
    );

VOID
SrvLeaseTableRelease(
    IN PSRV_LEASE_TABLE* ppLeaseTable
    );

NTSTATUS
SrvLeaseRecordFind(
    IN PLWIO_SRV_CONNECTION Connection,
    IN PGUID ClientLeaseKey,
    OUT PSRV_LEASE_RECORD* ppLeaseRecord
    );

NTSTATUS
SrvLeaseRecordFindOrAllocate(
    IN PLWIO_SRV_CONNECTION Connection,
    IN PGUID ClientLeaseKey,
    OUT PSRV_LEASE_RECORD* ppLeaseRecord
    );

VOID
SrvLeaseRecordAcquire(
    IN PSRV_LEASE_RECORD pLeaseRecord
    );

VOID
SrvLeaseRecordRelease(
    IN PSRV_LEASE_RECORD* ppLeaseRecord
    );

NTSTATUS
SrvLeaseRecordAddOplock(
    IN PSRV_LEASE_RECORD pLeaseRecord,
    IN HANDLE hOplock
    );

VOID
SrvLeaseRecordRemoveOplock(
    IN HANDLE hOplock
    );

NTSTATUS
SrvLeaseRecordIterCreate(
    IN PSRV_LEASE_RECORD pLeaseRecord,
    IN OUT PSRV_LEASE_RECORD_ITERATOR* ppIter
    );

VOID
SrvLeaseRecordIterFree(
    PSRV_LEASE_RECORD_ITERATOR* ppIter
    );

VOID
SrvLeaseRecordIterReset(
    PSRV_LEASE_RECORD_ITERATOR pIter
    );

HANDLE
SrvLeaseRecordIterNext(
    PSRV_LEASE_RECORD_ITERATOR pIter
    );

VOID
SrvLeaseRecordSwitchHandle(
    IN HANDLE hOplock
    );

IO_LEASE_STATE
SrvLeaseMapSmb2ToIoLeaseState(
    IN ULONG Smb2LeaseState
    );

ULONG
SrvLeaseMapIoToSmb2LeaseState(
    IN IO_LEASE_STATE IoLeaseState
    );

BOOLEAN
SrvIsLeaseKeyEqual(
    IN PGUID LeaseKey1,
    IN PGUID LeaseKey2
    );

// processinfo.c

NTSTATUS
SrvInitProcessInfoState(
    PSRV_PROCESS_INFO_STATE     pInfoState,
    IO_FILE_HANDLE              hFile,
    ULONG                       ulOutputBufferLen,
    USHORT                      usInfoClass
    );

void
SrvFiniProcessInfoState(
    PSRV_PROCESS_INFO_STATE     pInfoState
    );

GET_INFO_CLASS_GET_FUNC SrvGetUnsupportedInfo;
GET_INFO_CLASS_GET_FUNC SrvGetFileInfoGeneric_WithFileName;
GET_INFO_CLASS_GET_FUNC SrvGetFileInfoGeneric;
GET_INFO_CLASS_GET_FUNC SrvGetFileInfoGeneric_WithString;
GET_INFO_CLASS_GET_FUNC SrvGetFileSystemInfoGeneric;
GET_INFO_CLASS_GET_FUNC SrvGetFileSystemInfoGeneric_WithString;

GET_INFO_CLASS_MARSHAL_FUNC SrvMarshalUnsupportedInfo;

NTSTATUS
SrvGetFileOrVolumeInfoGeneric(
    PSRV_EXEC_CONTEXT                   pExecContext,
    PSRV_PROCESS_INFO_STATE             pInfoState,
    PGET_INFO_CLASS_DISPATCH_ENTRY      pInfoEntry,
    PIO_QUERY_FILE_OR_VOLUME_INFO_FUNC  pQueryFunc
    );

NTSTATUS
SrvGetFileOrVolumeInfoGeneric_WithString(
    PSRV_EXEC_CONTEXT                   pExecContext,
    PSRV_PROCESS_INFO_STATE             pInfoState,
    PGET_INFO_CLASS_DISPATCH_ENTRY      pInfoEntry,
    PIO_QUERY_FILE_OR_VOLUME_INFO_FUNC  pQueryFunc,
    BOOLEAN                             bHonorBufferLimit
    );

NTSTATUS
SrvGetTableInfo(
    PSRV_EXEC_CONTEXT pExecContext,
    PSRV_PROCESS_INFO_STATE pInfoState,
    GET_INFO_CLASS_DISPATCH_ENTRY *Table,
    size_t TableNumElements
    );

NTSTATUS
SrvMarshalTableInfo(
    PSRV_EXEC_CONTEXT pExecContext,
    PSRV_PROCESS_INFO_STATE pInfoState,
    GET_INFO_CLASS_DISPATCH_ENTRY *Table,
    size_t TableNumElements,
    PBYTE pDataCursor,
    ULONG ulBytesAvailalbe,
    PULONG pulBytesUsed
    );

// srvsession2.c

NTSTATUS
SrvSession2TableInit(
    PSRV_SESSION2_TABLE pTable
    );

VOID
SrvSession2TableShutdown(
    IN OUT PSRV_SESSION2_TABLE pTable
    );

NTSTATUS
SrvSession2Lookup(
    IN ULONG64 ullUid,
    OUT PLWIO_SRV_SESSION_2 *ppSession
    );


#endif /* __ELEMENTSAPI_H__ */
