windows-nt/Source/XPSP1/NT/base/fs/srv/srvblock.h
2020-09-26 16:20:57 +08:00

3723 lines
95 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++ BUILD Version: 0003 // Increment this if a change has global effects
Copyright (c) 1989 Microsoft Corporation
Module Name:
srvblock.h
Abstract:
This module defines the standard header for data blocks maintained
by the LAN Manager server.
Author:
Chuck Lenzmeier (chuckl) 1-Dec-1989
David Treadwell (davidtr)
Revision History:
--*/
#ifndef _SRVBLOCK_
#define _SRVBLOCK_
//#include "srvtypes.h"
//
// The following define the various types of data blocks used by the
// server.
//
// *** The pool tag array in heapmgr.c must be maintained in concert
// with these definitions.
//
#define BlockTypeGarbage 0x00
#define BlockTypeBuffer 0x01
#define BlockTypeConnection 0x02
#define BlockTypeEndpoint 0x03
#define BlockTypeLfcb 0x04
#define BlockTypeMfcb 0x05
#define BlockTypeRfcb 0x06
#define BlockTypeSearch 0x07
#define BlockTypeSearchCore 0x08
#ifdef INCLUDE_SMB_PERSISTENT
#define BlockTypeByteRangeLock 0x09
#endif
#define BlockTypeSession 0x0A
#define BlockTypeShare 0x0B
#define BlockTypeTransaction 0x0C
#define BlockTypeTreeConnect 0x0D
#define BlockTypeWaitForOplockBreak 0x0E
#define BlockTypeCommDevice 0x0F
#define BlockTypeWorkContextInitial 0x10
#define BlockTypeWorkContextNormal 0x11
#define BlockTypeWorkContextRaw 0x12
#define BlockTypeWorkContextSpecial 0x13
#define BlockTypeCachedDirectory 0x14
// The following "blocks" do NOT have block headers.
#define BlockTypeDataBuffer 0x15
#define BlockTypeTable 0x16
#define BlockTypeNonpagedHeader 0x17
#define BlockTypePagedConnection 0x18
#define BlockTypePagedRfcb 0x19
#define BlockTypeNonpagedMfcb 0x1A
#define BlockTypeTimer 0x1B
#define BlockTypeAdminCheck 0x1C
#define BlockTypeWorkQueue 0x1D
#define BlockTypeDfs 0x1E
#define BlockTypeLargeReadX 0x1F
#define BlockTypeAdapterStatus 0x20
#define BlockTypeShareRemark 0x21
#define BlockTypeShareSecurityDescriptor 0x22
#define BlockTypeVolumeInformation 0x23
#define BlockTypeFSName 0x24
#define BlockTypeNameInfo 0x25
#define BlockTypeDirectoryInfo 0x26
#define BlockTypeDirCache 0x27
#define BlockTypeMisc 0x28
#define BlockTypeSnapShot 0x29
#ifdef INCLUDE_SMB_PERSISTENT
#define BlockTypePersistentState 0x2A
#define BlockTypePersistentBitMap 0x2B
#define BlockTypePersistShareState 0x2C
// The following is defined just to know how many types there are.
#define BlockTypeMax 0x2D
#else
// The following is defined just to know how many types there are.
#define BlockTypeMax 0x2A
#endif
//
// The following define the various states that blocks can be in.
// Initializing is used (relatively rarely) to indicate that
// creation/initialization of a block is in progress. Active is the
// state blocks are usually in. Closing is used to indicate that a
// block is being prepared for deletion; when the reference count on the
// block reaches 0, the block will be deleted. Dead is used when
// debugging code is enabled to indicate that the block has been
// deleted.
//
#define BlockStateDead 0x00
#define BlockStateInitializing 0x01
#define BlockStateActive 0x02
#define BlockStateClosing 0x03
// The following is defined just to know how many states there are.
#define BlockStateMax 0x04
//
// ALLOCATE_NONPAGED_POOL is a macro that translates to a call to
// SrvAllocateNonPagedPool if debugging is not enabled or to
// SrvAllocateNonPagedPoolDebug if it is enabled.
// DEALLOCATE_NONPAGED_POOL translates to SrvFreeNonPagedPool or
// SrvFreeNonPagedPoolDebug. The Srv routines are used to track pool
// usage by the server.
//
//
// When POOL_TAGGING is on, we pass the block type through to
// SrvAllocateNonPagedPool so that it can pass a tag to the pool
// allocator.
//
#ifdef POOL_TAGGING
#define ALLOCATE_NONPAGED_POOL(size,type) \
SrvAllocateNonPagedPool( (size), (type) )
#else
#define ALLOCATE_NONPAGED_POOL(size,type) \
SrvAllocateNonPagedPool( (size) )
#endif
#define DEALLOCATE_NONPAGED_POOL(addr) SrvFreeNonPagedPool( (addr) )
//
// Routines that track server nonpaged pool usage in order to support the
// "maxnonpagedmemoryusage" configuration parameter.
//
PVOID SRVFASTCALL
SrvAllocateNonPagedPool (
IN CLONG NumberOfBytes
#ifdef POOL_TAGGING
,IN CLONG BlockType
#endif
);
VOID SRVFASTCALL
SrvFreeNonPagedPool (
IN PVOID Address
);
VOID SRVFASTCALL
SrvClearLookAsideList(
PLOOK_ASIDE_LIST l,
VOID (SRVFASTCALL *FreeRoutine )( PVOID )
);
//
// The _HEAP macros are like the _NONPAGED_POOL macros, except they
// operate on paged pool. The "HEAP" name is historical, from the
// days when the server used process heap instead of paged pool.
//
// *** When SRVDBG2 is enabled, all server control blocks and all
// reference history blocks must be allocated from nonpaged pool,
// because SrvUpdateReferenceHistory touches these thing while
// holding a spin lock (i.e., at raised IRQL). To make this easy,
// the ALLOCATE_HEAP and FREE_HEAP macros are modified to use
// nonpaged pool. This means that ALL memory allocated by the
// server comes out of nonpaged pool when SRVDBG2 is on.
//
#if SRVDBG2
#define ALLOCATE_HEAP(size,type) ALLOCATE_NONPAGED_POOL( (size), (type) )
#define ALLOCATE_HEAP_COLD(size,type) ALLOCATE_NONPAGED_POOL( (size), (type) )
#define FREE_HEAP(addr) DEALLOCATE_NONPAGED_POOL( (addr) )
#else // SRVDBG2
//
// When POOL_TAGGING is on, we pass the block type through to
// SrvAllocateNonPagedPool so that it can pass a tag to the pool
// allocator.
//
#ifdef POOL_TAGGING
#define ALLOCATE_HEAP(size,type) SrvAllocatePagedPool( PagedPool, (size), (type) )
#define ALLOCATE_HEAP_COLD(size,type) SrvAllocatePagedPool( (PagedPool | POOL_COLD_ALLOCATION), (size), (type) )
#else
#define ALLOCATE_HEAP(size,type) SrvAllocatePagedPool( PagedPool, (size) )
#define ALLOCATE_HEAP_COLD(size,type) SrvAllocatePagedPool( (PagedPool | POOL_COLD_ALLOCATION), (size) )
#endif
#define FREE_HEAP(addr) SrvFreePagedPool( (addr) )
#endif // else SRVDBG2
//
// Routines that track server paged pool usage in order to support the
// "maxpagedmemoryusage" configuration parameter.
//
PVOID SRVFASTCALL
SrvAllocatePagedPool (
IN POOL_TYPE PoolType,
IN CLONG NumberOfBytes
#ifdef POOL_TAGGING
,IN CLONG BlockType
#endif
);
VOID SRVFASTCALL
SrvFreePagedPool (
IN PVOID Address
);
//
// SHARE_TYPE is an enumerated type used to indicate what type of
// resource is being shared. This type corresponds to the server
// table StrShareTypeNames. Keep the two in sync.
//
typedef enum _SHARE_TYPE {
ShareTypeDisk,
ShareTypePrint,
ShareTypePipe,
ShareTypeWild // not a real share type, but can be specified in tcon
} SHARE_TYPE, *PSHARE_TYPE;
//
// SHARE_SNAPSHOT represents a snapshot availible for this share.
//
typedef struct _SHARE_SNAPSHOT
{
LIST_ENTRY SnapShotList;
ULONG Flags;
HANDLE SnapShotRootDirectoryHandle;
LARGE_INTEGER Timestamp;
UNICODE_STRING SnapShotName; // "SS@GMT-YYYY.MM.DD-HH.MM.SS"
UNICODE_STRING SnapShotPath;
} SHARE_SNAPSHOT, *PSHARE_SNAPSHOT;
#define SNAPSHOT_NAME_LENGTH (strlen("@GMT-YYYY.MM.DD-HH.MM.SS")+1)*sizeof(WCHAR)
#define SNAPSHOT_NAME_FORMAT L"@GMT-%04d.%02d.%02d-%02d.%02d.%02d"
#define SRV_SNAP_SHARE_NOT_FOUND 1
//
// For each resource that the server shares, a Share Block is
// maintained. The global share list is anchored at SrvShareHashTable. A
// list of active tree connections using a resource is anchored in the
// Share Block.
//
typedef struct _SHARE {
BLOCK_HEADER BlockHeader; // must be first element
LIST_ENTRY TreeConnectList;
LIST_ENTRY GlobalShareList;
HANDLE RootDirectoryHandle;
UNICODE_STRING ShareName;
UNICODE_STRING NtPathName;
UNICODE_STRING DosPathName;
UNICODE_STRING Remark;
ULONG ShareNameHashValue;
union {
struct {
UNICODE_STRING Name;
OEM_STRING OemName;
} FileSystem;
HANDLE hPrinter;
} Type;
ULONG MaxUses;
ULONG CurrentUses;
ULONG CurrentRootHandleReferences; // used for removable devices
LONG QueryNamePrefixLength;
PSECURITY_DESCRIPTOR SecurityDescriptor; // for tree connects
PSECURITY_DESCRIPTOR FileSecurityDescriptor; // file acls on shares
SHARE_TYPE ShareType;
BOOLEAN Removable; // Is the share storage removable?
BOOLEAN SpecialShare;
BOOLEAN IsDfs; // Is this share in the Dfs?
BOOLEAN IsDfsRoot; // Is this share the root of a Dfs?
BOOLEAN PotentialSystemFile; // Are files in this share potentially
// system files?
BOOLEAN IsCatchShare; // Should the SRVCATCH code be active
BOOLEAN UniqueNames; // Are all names unique or are shortnames used?
#ifdef INCLUDE_SMB_IFMODIFIED
BOOLEAN UsnCapable; // does this volume have a USN journal?
#endif
//
// These flags are returned to the client on a tree connect to instruct the client
// how it can cache the files on this share. The server does not interpret these
// flags -- it is the client's responsibility to do the right thing.
//
ULONG CSCState;
#ifdef INCLUDE_SMB_PERSISTENT
BOOLEAN AllowPersistentHandles; // allow persistent handles on this volume?
PERSISTENT_INFO; // persistent info
PVOID PersistentStateFile;
#endif
PSRV_LOCK SecurityDescriptorLock;
LIST_ENTRY SnapShots;
PSRV_LOCK SnapShotLock;
// WCHAR ShareNameData[ShareName.MaximumLength];
// WCHAR NtPathNameData[PathName.MaximumLength];
// WCHAR DosPathNameData[PathName.MaximumLength];
// SECURITY_DESCRIPTOR SecurityDescriptor;
} SHARE, *PSHARE;
//
// For each network that the server uses, an Endpoint Block is
// maintained. An ENDPOINT contains the network name (for
// administrative purposes), the endpoint name (server address), the
// endpoint (file) handle, a pointer to the endpoint object, a pointer
// to the transport provider's device object, and state information.
// The global endpoint list is anchored at SrvEndpointList. A list of
// active connections created using an endpoint is anchored in the
// Endpoint Block.
//
#if SRVDBG29
#define HISTORY_LENGTH 256
typedef struct {
ULONG Operation;
PVOID Connection;
BLOCK_HEADER ConnectionHeader;
} HISTORY, *PHISTORY;
#define UpdateConnectionHistory(_op,_endp,_conn) { \
PHISTORY history = &(_endp)->History[(_endp)->NextHistoryLocation++]; \
if ((_endp)->NextHistoryLocation >= HISTORY_LENGTH) { \
(_endp)->NextHistoryLocation = 0; \
} \
history->Operation = *(PULONG)(_op); \
history->Connection = (_conn); \
if (_conn) { \
history->ConnectionHeader = *(PBLOCK_HEADER)(_conn); \
} \
}
#endif
struct _CONNECTION;
typedef struct _ENDPOINT {
BLOCK_HEADER BlockHeader; // must be first element
//
// List of free connections.
//
LIST_ENTRY FreeConnectionList;
//
// Table of connections. We use a table instead of a list in order
// to speed up lookup of IPX connections based on the SID stored in
// the SMB header.
//
TABLE_HEADER ConnectionTable;
ORDERED_LIST_ENTRY GlobalEndpointListEntry;
//
// Handle and file/device objects for connection-oriented endpoint
// or for connectionless server data socket.
//
HANDLE EndpointHandle;
PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
PULONG IpxMaxPacketSizeArray;
ULONG MaxAdapters;
//
// Handle and file/device objects for connectionless NetBIOS name
// socket.
//
HANDLE NameSocketHandle;
PFILE_OBJECT NameSocketFileObject;
PDEVICE_OBJECT NameSocketDeviceObject;
PDRIVER_DISPATCH FastTdiSend;
PDRIVER_DISPATCH FastTdiSendDatagram;
TDI_ADDRESS_IPX LocalAddress;
ULONG FreeConnectionCount;
ULONG TotalConnectionCount;
//
// Various flags
//
struct {
ULONG IsConnectionless : 1; // connectionless transport?
ULONG NameInConflict : 1; // unable to claim name?
ULONG IsPrimaryName : 1; // set if not an alternate name
ULONG IsNoNetBios : 1; // set if we are direct hosting on a VC
ULONG RemapPipeNames : 1; // set if we are remapping pipe names for clusters
};
WCHAR NetworkAddressData[12 + 1];
UNICODE_STRING NetworkName; // administrative name
UNICODE_STRING TransportName; // e.g., "\Device\Nbf_Elnkii01"
UNICODE_STRING ServerName; // e.g., L"NTSERVER"
ANSI_STRING TransportAddress; // e.g., "NTSERVER "
UNICODE_STRING NetworkAddress;
UNICODE_STRING DomainName; // domain being served by this endpoint
OEM_STRING OemDomainName; // oem version of domain name
// WCHAR NetworkNameData[NetworkName.MaximumLength/2];
// WCHAR TransportNameData[TransportName.MaximumLength/2];
// WCHAR ServerName[ ServerName.MaximumLength/2 ];
// CHAR TransportAddressData[TransportAddress.MaximumLength];
// WCHAR DomainNameData[ DNLEN + 1];
// CHAR OemDomainNameData[ DNLEN+1 ]
BOOLEAN AlternateAddressFormat; // should this endpoint be included when
// enumerating?
#if SRVDBG29
ULONG NextHistoryLocation;
HISTORY History[HISTORY_LENGTH];
#endif
} ENDPOINT, *PENDPOINT;
//
// Size of search hash table (must be a power of 2)
//
#define SEARCH_HASH_TABLE_SIZE 4
typedef struct _HASH_TABLE_ENTRY {
LIST_ENTRY ListHead;
BOOLEAN Dirty;
} HASH_TABLE_ENTRY, *PHASH_TABLE_ENTRY;
//
// When we discover something which is a directory, we place the name
// in this per-connection cache for quick re-use for CheckPath.
//
typedef struct {
BLOCK_HEADER;
LIST_ENTRY ListEntry; // list is linked through this element
UNICODE_STRING DirectoryName; // canonicalized name of this directory
USHORT Tid; // DirectoryName is relative to this tid
ULONG TimeStamp; // Tick count when this element was cached
} CACHED_DIRECTORY, *PCACHED_DIRECTORY;
//
// For each connection (virtual circuit) that is created, a Connection
// Block is maintained. All connections made over a single endpoint are
// linked through that endpoint. Tables of sessions, tree connects, and
// files created using a connection are anchored in the connection
// block.
//
// The Lock field in the connection protects the data in the connection
// and the data structures associated with the connection, such as
// the tree connects and sessions. However, the list of connections
// linked off the endpoint is protected by the endpoint lock, and
// LFCBs and RFCBs associated with a connection are protected by
// the MFCB's lock.
//
typedef struct _PAGED_CONNECTION {
PAGED_HEADER PagedHeader;
//
// List of active transactions
//
LIST_ENTRY TransactionList;
//
// This list is maintained in order of access, so the entry at the top
// of the list is the oldest, the entry at the bottom is the youngest.
//
LIST_ENTRY CoreSearchList;
//
// This information is used to determine whether oplocks and Raw
// I/O's are allowed. This is determined by information obtained by
// querying the transport provider using TDI_QUERY_CONNECTION_INFO.
//
LARGE_INTEGER LinkInfoValidTime;
LARGE_INTEGER Throughput;
LARGE_INTEGER Delay;
//
// Table headers for session, tree connect, and search tables.
//
TABLE_HEADER SessionTable;
TABLE_HEADER TreeConnectTable;
TABLE_HEADER SearchTable;
HANDLE ConnectionHandle;
//
// The number of sessions active on the connection.
//
USHORT CurrentNumberOfSessions;
USHORT CurrentNumberOfCoreSearches;
//
// Hash table for picking out duplicate core searches
//
HASH_TABLE_ENTRY SearchHashTable[SEARCH_HASH_TABLE_SIZE];
//
// A string for the client's name. The Buffer field points to the
// leading slashes (below), the MaximumLength is
// (COMPUTER_NAME_LENGTH + 3) * sizeof(WCHAR), and Length is the
// number of characters in the name that are not blanks *
// sizeof(WHCAR).
//
UNICODE_STRING ClientMachineNameString;
//
// The following two fields make up the client's name in the form
// "\\client ", including a trailing NULL.
//
WCHAR LeadingSlashes[2];
WCHAR ClientMachineName[COMPUTER_NAME_LENGTH+1];
//
// The encryption key obtained from LsaCallAuthenticationPackage.
// This is a per-VC value--any logon on a given VC uses this
// encryption key.
//
UCHAR EncryptionKey[MSV1_0_CHALLENGE_LENGTH];
//
// If we have an NT5 client, this is its build number (if non-zero)
//
ULONG ClientBuildNumber;
//
// If the client has a persistent connection, here's the info for this
// record in the state file.
//
#ifdef INCLUDE_SMB_PERSISTENT
PERSISTENT_INFO; // persistent info
#endif
//
// Have we logged an invalid SMB for this client yet? We use this
// flag to keep a single client from flooding the event log
//
BOOLEAN LoggedInvalidSmb;
#if SRVNTVERCHK
//
// Have we determined that the client's NT build number is too old to
// allow it to connect to this server?
//
BOOLEAN ClientTooOld;
#endif
} PAGED_CONNECTION, *PPAGED_CONNECTION;
#define MAX_SAVED_RESPONSE_LENGTH 100
typedef struct _CONNECTION {
QUEUEABLE_BLOCK_HEADER ; // must be first element
/* start of spin lock cache line */
//
// Per-connection spin lock.
//
KSPIN_LOCK SpinLock;
//
// Points to the endpoint spinlock that guards this connection's
// entry in the endpoint connection table.
//
PKSPIN_LOCK EndpointSpinLock;
//
// This is the WORK_QUEUE we are queueing on, which may not be the
// same as PreferredWorkQueue due to load balancing
//
PWORK_QUEUE CurrentWorkQueue;
//
// A countdown for the number of operations we'll do before we try
// to pick a better processor for this connection
//
ULONG BalanceCount;
//
// Cached Rfcb
//
struct _RFCB *CachedRfcb;
ULONG CachedFid;
//
// BreakIIToNoneJustSent is set when a oplock break II to none is
// sent, and reset whenever an SMB is received. If a raw read
// arrives while this is set, the raw read is rejected.
//
BOOLEAN BreakIIToNoneJustSent;
//
// Raw io enabled
//
BOOLEAN EnableRawIo;
//
// Sid represents the connection's location in the endpoint's
// connection table.
//
USHORT Sid;
// The SidIndex allows us to use all the 16 bits for the index. For
// regular connections this prevents the aliasing problem that can occur
// in using the IXPSID index since the IPX sequence number takes up 4 bits
USHORT SidIndex;
// additional USHORT to satisfy alignment on dword boundaries
USHORT Pad;
//
// Pointer to the endpoint, fileobject, and deviceobject
//
PENDPOINT Endpoint;
PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
//
// The maximum message size we can send over this connection.
//
ULONG MaximumSendSize;
//
// This is the WORK_QUEUE we would prefer to be on, because this
// queue assigns work to the same procesor that is handling the
// adaptor's DPCs
//
PWORK_QUEUE PreferredWorkQueue;
//
// Table header for file table.
//
TABLE_HEADER FileTable;
//
// The SMB dialect chosen for this connection. Used in fsd.
//
SMB_DIALECT SmbDialect;
//
// List of active work items associated with the connection.
//
LIST_ENTRY InProgressWorkItemList;
//
// Stores the time of the last oplock break resp processed. This is
// used to synchronize readraw processing with the oplock break
// processing.
//
ULONG LatestOplockBreakResponse;
//
// The following two fields descibe operations in progress on this
// connection. It is possible that there are multiple oplock breaks
// in progress. Also, there is a brief window when multiple raw
// reads can be active -- after we've sent the response to one raw
// read, but before we've done postprocessing (so it looks like the
// first one is still in progress), we could receive another raw
// read request.
//
// Interaction between the two fields are controlled using
// SrvFsdSpinLock (see the block comment in oplock.c for details).
//
LONG OplockBreaksInProgress;
ULONG RawReadsInProgress;
//
// Are oplocks allowed?
//
BOOLEAN OplocksAlwaysDisabled;
BOOLEAN EnableOplocks;
//
// Is the client coming in over IPX?
//
BOOLEAN DirectHostIpx;
//
// Are security signatures currently active for this connection?
// Security signatures are not supported for Direct Host IPX connections
// and some W9x clients
//
BOOLEAN SmbSecuritySignatureActive;
union {
//
// The following struct of this union holds relevant state
// when the client is connecting over direct host IPX.
// IpxAddress holds the client's IPX address, when the client
// 'connects' over IPX.
//
struct {
USHORT SequenceNumber;
USHORT LastResponseLength;
USHORT LastResponseBufferLength;
USHORT LastUid;
USHORT LastTid;
NTSTATUS LastResponseStatus;
ULONG IpxDuplicateCount;
ULONG IpxDropDuplicateCount;
ULONG StartupTime;
TDI_ADDRESS_IPX IpxAddress;
PVOID LastResponse;
};
//
// This struct holds relevant state when the client is using
// a virtual circuit.
//
struct {
//
// The following fields are used for security signatures.
//
MD5_CTX Md5Context;
ULONG SmbSecuritySignatureIndex;
// If we are unable to allocate a WORK_CONTEXT
// at receive indicate time, the receive is done
// in SrvFsdServiceNeedResourceQueue. Depending
// on the received SMB, we sometimes do not send
// a response SMB. Since the Tdi lookahead data
// is not available when SrvFsdServiceNeedResourceQueue
// is run, we have to remember not to advance the signature
// index for the response.
BOOLEAN NoResponseSignatureIndex;
//
// The following field, if non-zero is the IP address of the client
//
ULONG ClientIPAddress;
};
};
//
// Pointer to paged part of connection block.
//
PPAGED_CONNECTION PagedConnection;
//
// Per-connection interlock.
//
KSPIN_LOCK Interlock;
//
// Quadword align list entries and large ints
//
LIST_ENTRY EndpointFreeListEntry;
//
// A list of deferred oplock work break items. Oplock breaks are
// deferred if a read raw is in progress, or if the server runs
// out of work context blocks, and cannot send the oplock break
// request.
//
LIST_ENTRY OplockWorkList;
//
// List of RFCBs with batch oplocks that have been cached after
// being closed by the client. Count of such RFCBs.
//
LIST_ENTRY CachedOpenList;
ULONG CachedOpenCount;
//
// List of directories which have been recently identified. This is a list of
// CACHED_DIRECTORY entries.
//
LIST_ENTRY CachedDirectoryList;
ULONG CachedDirectoryCount;
//
// Security context handle for the extensible security negotiate buffer.
//
CtxtHandle NegotiateHandle;
//
// The following represent consumer capabilities.
//
ULONG ClientCapabilities;
//
// Per-connection resource.
//
SRV_LOCK Lock;
//
// Lock for dealing with the license server
//
SRV_LOCK LicenseLock;
//
// Oem version of the client machine name string.
//
OEM_STRING OemClientMachineNameString;
//
// Head of singly linked list of cached transactions.
//
SLIST_HEADER CachedTransactionList;
LONG CachedTransactionCount;
//
// The time when the last message was received for this connection
//
ULONG LastRequestTime;
//
// If we are on the OnNeedResourceQueue for a pending recieve, this
// is the amount of data that was indicated to us.
//
ULONG BytesAvailable;
//
// OnNeedResource is true if this connection is on the global need
// recource queue. This happens if it is waiting for a work context
// block to complete a pending receive or an oplock break request.
//
BOOLEAN OnNeedResourceQueue;
//
// NotReusable is set when an operation fails in such a way that the
// server's idea of the connection state may be different than the
// transport's. For example, a server-initiated disconnect failed.
// If we tried to reuse the connection (by returning it from a
// connect indication), the transport would get confused. When
// NotReusable is set, SrvDereferenceConnection frees the connection
// instead of putting it on the endpoint's free list.
//
BOOLEAN NotReusable;
//
// DisconnectPending indicates that a disconect indication has been
// received from the transport. ReceivePending indicates that the
// server could not assign a work item to handle a receive indication.
//
BOOLEAN DisconnectPending;
BOOLEAN ReceivePending;
//
// Oem version of the client name. We need this because we could
// not do unicode operations in the fsd, where we initially get our
// computer name.
//
CHAR OemClientMachineName[COMPUTER_NAME_LENGTH+1];
//
// Information about the client context.
//
UNICODE_STRING ClientOSType;
UNICODE_STRING ClientLanManType;
UCHAR BuiltinSavedResponse[MAX_SAVED_RESPONSE_LENGTH];
// Used to monitor how many work contexts a client is using up
LONG InProgressWorkContextCount;
LONG OperationsPendingOnTransport;
BOOLEAN IsConnectionSuspect;
DISCONNECT_REASON DisconnectReason;
} CONNECTION, *PCONNECTION;
//
// For each session that is created, a Session Block is maintained. All
// sessions created over a single connection are linked through a table
// owned by that connection. A list of files opened using a session can
// be obtained by searching the file table owned by the connection
// block.
//
// This is copied from ntmsv1_0.h
#define MSV1_0_USER_SESSION_KEY_LENGTH 16
typedef struct _SESSION {
//
// *** NOTE: The reference count field in the session block
// header is not used! Instead, the reference count is
// in the NonpagedHeader structure.
//
BLOCK_HEADER BlockHeader;
PNONPAGED_HEADER NonpagedHeader;
ULONG CurrentFileOpenCount; // count of files open on the session
ULONG CurrentSearchOpenCount; // count of searches open on the session
ORDERED_LIST_ENTRY GlobalSessionListEntry;
PCONNECTION Connection;
//
// If clients are using the GSS-style authentication, we query the
// UserHandle for the user and domain names. If they are using
// old-style authentication, we store the names here. In any case,
// code that needs access to the user and/or domain names should
// call SrvGetUserAndDomainName() and SrvReleaseUserAndDomainName()
//
UNICODE_STRING NtUserName;
UNICODE_STRING NtUserDomain;
LARGE_INTEGER StartTime;
LARGE_INTEGER LastUseTime; // for autologoff
LARGE_INTEGER LogOffTime; // for forced logoff
LARGE_INTEGER KickOffTime; // for forced logoff
LARGE_INTEGER LastExpirationMessage; // for forced logoff
LUID LogonId;
CHAR NtUserSessionKey[MSV1_0_USER_SESSION_KEY_LENGTH];
CHAR LanManSessionKey[MSV1_0_LANMAN_SESSION_KEY_LENGTH];
CtxtHandle UserHandle; // Security handle to this user
USHORT MaxBufferSize; // Consumer's maximum buffer size
USHORT MaxMpxCount; // Actual max multiplexed pending requests
USHORT Uid;
BOOLEAN UsingUppercasePaths; // Must paths be uppercased?
BOOLEAN GuestLogon; // Is the client logged on as a guest?
BOOLEAN EncryptedLogon; // Was an encrypted password sent?
BOOLEAN LogoffAlertSent;
BOOLEAN TwoMinuteWarningSent;
BOOLEAN FiveMinuteWarningSent;
BOOLEAN IsNullSession; // Is client using a null session?
BOOLEAN IsAdmin; // Is this an administrative user?
BOOLEAN IsLSNotified; // Does license server know about this user?
BOOLEAN LogonSequenceInProgress; // Are we in the middle of an extended logon sequence?
BOOLEAN IsSessionExpired; // Do we need to reauthenticate?
HANDLE hLicense; // if( IsLSNotified ) this is License handle
//
// If the client has a persistent connection, here's the info for this
// record in the state file.
//
#ifdef INCLUDE_SMB_PERSISTENT
PERSISTENT_INFO; // persistent info
#endif
#if SRVNTVERCHK
//
// Have we determined that we don't like this client's domain?
//
BOOLEAN ClientBadDomain;
#endif
//CHAR UserNameBuffer[UserName.MaximumLength];
} SESSION, *PSESSION;
//
// For each tree connect that is made, a Tree Connect Block is
// maintained. All tree connects made over a single connection are
// linked through a table owned by that connection. All tree connects
// made to a single shared resource are linked through that share block.
// A list of files opened using a tree connect can be obtained by
// searching the file table owned by the connection block.
//
typedef struct _TREE_CONNECT {
//
// *** NOTE: The reference count field in the tree connect block
// header is not used! Instead, the reference count is
// in the NonpagedHeader structure.
//
BLOCK_HEADER BlockHeader;
PNONPAGED_HEADER NonpagedHeader;
PCONNECTION Connection;
PSESSION Session;
PSHARE Share;
ORDERED_LIST_ENTRY GlobalTreeConnectListEntry;
ULONG CurrentFileOpenCount;
LIST_ENTRY ShareListEntry;
LIST_ENTRY PrintFileList; // only if print share
LARGE_INTEGER StartTime;
UNICODE_STRING ServerName;
BOOLEAN RemapPipeNames;
USHORT Tid;
} TREE_CONNECT, *PTREE_CONNECT;
//
// Master File Control Block (MFCB) -- one per named file that is open
// at least once. Used to support compatibility mode and oplocks.
//
// Local File Control Block (LFCB) -- one for each local open instance.
// Represents local file object/handle. There may be multiple
// LFCBs linked to a single MFCB.
//
// Remote File Control Block (RFCB) -- one for each remote open instance.
// Represents remote FID. There is usually one RFCB per LFCB, but
// multiple compatibility mode RFCBs may be linked to a single LFCB.
// Multiple remote FCB opens for a single file from a single session
// are folded into one RFCB, because old DOS redirectors only send
// one close.
//
//
// For each disk file that is open, a Master File Control Block (MFCB)
// is maintained. If a given file is open multiple times, there is one
// MFCB for the file and multiple LFCBs, one for each local open
// instance. All MFCBs are linked into the global Master File Table.
// The MFCB has a list of the LFCBs representing open instances for the
// file.
//
typedef struct _NONPAGED_MFCB {
union {
//
// When NONPAGED_MFCB structures are freed, they may be placed
// on the WORK_QUEUE's MfcbFreeList to avoid unnecessary Nonpaged
// pool activity. SingleListEntry is used for the linkage.
//
SINGLE_LIST_ENTRY SingleListEntry;
struct {
ULONG Type;
PVOID PagedBlock;
//
// We must serialize opens to the same file, since 2 concurrent opens
// may be compatibility mode opens. This lock also protects all data
// in this MFCB and the LFCBs and RFCBs associated with this MFCB.
//
SRV_LOCK Lock;
};
};
LARGE_INTEGER OpenFileSize;
ULONG OpenFileAttributes;
} NONPAGED_MFCB, *PNONPAGED_MFCB;
typedef struct _MFCB {
//
// *** NOTE: The reference count field in the mfcb block
// header is not used! Instead, the reference count is
// in the NonpagedHeader structure.
//
BLOCK_HEADER BlockHeader; // must be first element
PNONPAGED_MFCB NonpagedMfcb;
//
// All LFCBs for a given named file are linked to the parent MFCB.
//
LIST_ENTRY LfcbList;
//
// The count of active RFCB for this MFCB. This is used to coordinate
// compatibility opens with non-compatibility mode opens.
//
ULONG ActiveRfcbCount;
//
// The fully qualified name of the file is appended to the MFCB.
// The FileName field is a descriptor for the name.
//
UNICODE_STRING FileName;
//
// Mfcbs are linked into the MfcbHashTable by MfcbHashTableEntry
//
LIST_ENTRY MfcbHashTableEntry;
//
// FileNameHashValue is a hash value derived from the upper case
// version of FileName. It is used to speed up name comparisons, and to
// locate the hash entry
//
ULONG FileNameHashValue;
//
// CompatibilityOpen indicates whether the file is open in
// compatibility mode.
//
BOOLEAN CompatibilityOpen;
//
// Timestamp for SnapShot opens
//
LARGE_INTEGER SnapShotTime;
#if SRVCATCH
BOOLEAN SrvCatch;
#endif
// WCHAR FileNameData[FileName.MaximumLength/2];
} MFCB, *PMFCB;
//
// The MFCBs are all linked into the master MFCB hash table.
//
typedef struct {
LIST_ENTRY List; // the list of MFCBs in this bucket
PSRV_LOCK Lock; // protects this bucket's list
} MFCBHASH, *PMFCBHASH;
//
// For each instance of a local file open, a Local File Control Block
// (LFCB) is maintained. All LFCBs for a particular named file are
// linked through the MFCB for that file.
//
// LFCBs contain information that is specific to the local open, such
// as the file handle and a pointer to the file object. The LFCB also
// contains other information that is common to all child RFCBs, such
// as pointers to the owning connection and tree connect.
//
//
typedef struct _LFCB {
union {
BLOCK_HEADER BlockHeader; // must be first element
SINGLE_LIST_ENTRY SingleListEntry; // used when LFCB is freed
};
//
// Multiple remote opens of a file are folded into a single local
// open by linking the RFCBs to the parent LFCB.
//
LIST_ENTRY RfcbList;
//
// The number of associated active RFCBs.
//
ULONG HandleCount;
//
// LFCBs are linked into their MFCB's open file list.
//
PMFCB Mfcb;
LIST_ENTRY MfcbListEntry;
//
// Connection, Session, and TreeConnect are referenced pointers to
// the respective "owning" blocks.
//
PCONNECTION Connection;
PSESSION Session;
PTREE_CONNECT TreeConnect;
//
// GrantedAccess is the access obtained when the file was opened.
// For a compatibility mode open, this is the maximum access
// available to the client; individual opens may have less access.
//
ACCESS_MASK GrantedAccess;
//
// FileHandle is a handle to the open file. FileObject is a
// referenced pointer. DeviceObject is NOT a referenced pointer;
// the reference to the file object prevents the device object from
// going away.
//
HANDLE FileHandle;
PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
//
// FileMode tracks whether writethrough is enabled for this file
// object.
ULONG FileMode;
//
// The job ID of a print job corresponding to the opened file.
// This is only used for print file opens.
//
ULONG JobId;
//
// Cache these hot-path entry points.
//
PFAST_IO_READ FastIoRead;
PFAST_IO_WRITE FastIoWrite;
PFAST_IO_LOCK FastIoLock;
PFAST_IO_UNLOCK_SINGLE FastIoUnlockSingle;
PFAST_IO_MDL_READ MdlRead;
PFAST_IO_MDL_READ_COMPLETE MdlReadComplete;
PFAST_IO_PREPARE_MDL_WRITE PrepareMdlWrite;
PFAST_IO_MDL_WRITE_COMPLETE MdlWriteComplete;
PFAST_IO_READ_COMPRESSED FastIoReadCompressed;
PFAST_IO_WRITE_COMPRESSED FastIoWriteCompressed;
PFAST_IO_MDL_READ_COMPLETE_COMPRESSED MdlReadCompleteCompressed;
PFAST_IO_MDL_WRITE_COMPLETE_COMPRESSED MdlWriteCompleteCompressed;
//
// CompatibilityOpen indicates whether the file is open in
// compatibility mode.
//
BOOLEAN CompatibilityOpen;
//
// Has this file been modified by any clients? Used to determine when
// we should write out USN close records on file close.
//
#ifdef INCLUDE_SMB_IFMODIFIED
BOOLEAN FileUpdated;
#endif
} LFCB, *PLFCB;
//
// For each instance of a remote file open, a Remote File Control Block
// (RFCB) is maintained. The RFCB points to the LFCB that contains the
// local file handle. Normally RFCBs and LFCBs exist in one-to-one
// correspondence, but multiple compatibility mode opens are folded into
// a single local open, so that the server can enforce the appropriate
// sharing rules.
//
// RFCBs contain information that is specific to the remote open, such
// as the assigned FID, the PID of the creator, the granted access mask,
// and the current file position.
//
// All RFCBs for a single connection are linked through a table owned by
// that connection; the FID assigned to the RFCB represents an index
// into the file table. Pointers to the owning connection and tree
// connect can be found in the LFCB, which is pointed to by the RFCB. A
// list of files opened through a given tree connect can be obtained by
// searching the owning connection's file table for RFCBs whose parent
// LFCBs point to the tree connect.
//
#ifdef SLMDBG
#define SLMDBG_CLOSE 1
#define SLMDBG_RENAME 2
#define SLMDBG_TRACE_COUNT 32
#define SLMDBG_TRACE_DATA 32
typedef struct _RFCB_TRACE {
UCHAR Command;
UCHAR Flags;
TIME Time;
union {
struct {
ULONG Offset;
ULONG Length;
} ReadWrite;
struct {
ULONG Offset;
ULONG Length;
} LockUnlock;
} Data;
} RFCB_TRACE, *PRFCB_TRACE;
#endif
//
// WRITE_MPX_CONTEXT holds context associated with an active Write Block
// Multiplexed sequence.
//
// !!! This structure is probably big enough to be worth putting
// outside the RFCB.
//
#define MAX_GLOM_RUN_COUNT 8
typedef struct _WRITE_MPX_RUN {
USHORT Offset;
USHORT Length;
} WRITE_MPX_RUN, *PWRITE_MPX_RUN;
typedef struct _WRITE_MPX_CONTEXT {
//
// ReferenceCount counts the number of Write Mpx SMBs that are
// currently being processed. When this count goes to zero, and
// we have received the sequenced command that ends the current
// mux, we send the response. This method is needed to ensure
// that we don't process the mux SMBs out-of-order, which leads
// to performance problems, and even worse, data corruption,
// thanks to the mask-shifting method used by the Snowball redir.
//
ULONG ReferenceCount;
//
// Mask holds the logical OR of the masks received in multiplexed
// write requests. When an IPX client sends the last block of write
// mpx data, we send back MpxMask to indicate whether we lost any
// frames.
//
ULONG Mask;
//
// FileObject is a copy of the file object pointer from the LFCB.
//
PFILE_OBJECT FileObject;
//
// Mid holds the MID of the current multiplexed write. PreviousMid
// hold the MID of the previous one. This needs to be retained in
// order to deal with duplicated write mux SMBs -- if a duplicate
// SMB arrives AFTER the first SMB of the next write mux (with a new
// MID), we need to know to toss it, not kill the new write mux.
//
USHORT Mid;
USHORT PreviousMid;
//
// SequenceNumber holds the sequence number given in the last
// request of the mux. This needs to be retained because we
// may be simultaneously processing previous parts of the mux
// when we detect that we've received the sequenced comand.
//
USHORT SequenceNumber;
//
// Glomming is set if the current write mux series is being glommed
// into one large write.
//
// GlomPending is set when the indication for the first packet of
// a new write mux occurs. It is cleared when the FSP is done
// preparing the glomming operation. While GlomPending is set,
// subsequent packets of the write mux are queued to GlomDelayList.
//
BOOLEAN Glomming;
BOOLEAN GlomPending;
LIST_ENTRY GlomDelayList;
ULONG StartOffset;
USHORT Length;
BOOLEAN GlomComplete;
//
// MpxGlommingAllowed is set when the underlying file system
// supports MDL write.
//
BOOLEAN MpxGlommingAllowed;
PMDL MdlChain;
ULONG NumberOfRuns;
WRITE_MPX_RUN RunList[MAX_GLOM_RUN_COUNT];
} WRITE_MPX_CONTEXT, *PWRITE_MPX_CONTEXT;
#define NO_OPLOCK_BREAK_IN_PROGRESS ((UCHAR)-1)
typedef struct _PAGED_RFCB {
PAGED_HEADER PagedHeader;
//
// RFCBs are linked into their parent LFCB's compatibility open
// list.
//
LIST_ENTRY LfcbListEntry;
//
// Information about the last lock attempt by the client that failed.
//
LARGE_INTEGER LastFailingLockOffset;
//
// Current oplock break timeout.
//
LARGE_INTEGER OplockBreakTimeoutTime;
//
// FcbOpenCount indicates how many remote FCB opens this RFCB
// represents. (Whether an RFCB represents a compatibility mode
// open can be determined by looking at the LFCB.)
//
// *** Note that FCB opens are treated similarly to compatibility
// mode opens. However, soft compatibility maps compatibility
// opens into regular opens, but it does not change an FCB open
// into a non-FCB open. So it is possible to have an FCB open
// that is not a compatibility mode open.
//
CLONG FcbOpenCount;
//
// Per-file context for a direct host IPX smart card, if we have one.
// The smart card is willing to handle the read operations for this file if
// IpxSmartCardContext is not NULL.
//
PVOID IpxSmartCardContext;
//
// list of outstanding byte locks we have for this RFCB
//
#ifdef INCLUDE_SMB_PERSISTENT
LIST_ENTRY ByteRangeLocks;
//
// If the client has a persistent connection, here's the info for this
// record in the state file.
//
PERSISTENT_INFO; // persistent info
#endif
} PAGED_RFCB, *PPAGED_RFCB;
typedef struct _RFCB {
//
// The list entry in the RFCB's block header is used to queue the
// RFCB for oplock processing to the nonblocking worker thread work
// queue, which also contains work context blocks.
//
// *** Note that this is an unnamed field, so that its elements can
// can be referenced directly. The field names defined in
// QUEUEABLE_BLOCK_HEADER cannot be used elsewhere in this
// block.
//
QUEUEABLE_BLOCK_HEADER ; // must be first element
/* start of spin lock cache line */
//
// These booleans indicate whether we've already been granted
// read/write/lock access, thus saving a few instructions on every
// read/write/lock. These are checked during the file open.
//
BOOLEAN ReadAccessGranted; // TRUE, if read access in granted
BOOLEAN WriteAccessGranted; // TRUE, if write access is granted
BOOLEAN LockAccessGranted; // TRUE, if lock access is granted
BOOLEAN UnlockAccessGranted; // TRUE, if unlock access is granted
BOOLEAN AppendAccessGranted; // TRUE, if append access is granted
//
// CurrentPosition maintains the file position after the last Read,
// Write, or Seek by the client. This field is needed only to
// support relative Seeks. Since clients that use relative seeks only
// need 32-bits of file position, this field is maintained as a ULONG.
//
ULONG CurrentPosition;
//
// Type of this share. Accessed in the fsd.
//
SHARE_TYPE ShareType;
//
// The connection pointer is copied from the LFCB so that we can
// find the connection at DPC level (the LFCB is paged, as is the
// pointer to the LFCB in PagedRfcb).
//
PCONNECTION Connection;
//
// The LFCB is used to find the file handle, file object, etc.
//
PLFCB Lfcb;
//
// MpxGlommingAllowed is set when the underlying file system
// supports MDL write.
//
BOOLEAN MpxGlommingAllowed;
//
// The following two booleans describe the read mode, and blocking
// mode of a named pipe.
//
BOOLEAN BlockingModePipe; // TRUE = Blocking, FALSE = Nonblocking
BOOLEAN ByteModePipe; // TRUE = Byte mode, FALSE = Message mode
//
// Indicates whether this file has been written to.
//
BOOLEAN WrittenTo;
/* end of spin lock cache line */
//
// RawWriteSerializationList holds works items that have been queued
// pending completion of a raw write. When the raw write count is
// decremented to 0, this list is flushed by restarting all queued
// work items.
//
LIST_ENTRY RawWriteSerializationList;
//
// fid << 16. Used for key computations.
//
ULONG ShiftedFid;
//
// RawWriteCount counts the number of active raw writes. This is
// used to prevent the file handle from being closed while raw
// writes are in progress. If Raw writes are in progress when the
// close happens, we defer the cleanup until the rawwritecount goes
// to zero.
//
ULONG RawWriteCount;
//
// SavedError retains the error code when a raw read or a raw write
// in writebehind mode gets an error. The next access to the file
// will receive an error indication.
//
NTSTATUS SavedError;
//
// NumberOfLocks is the count of locks currently on the file.
// It is here to support the File APis and RFCB cacheing -- you can't
// cache an RFCB if it has locks in it.
//
LONG NumberOfLocks;
//
// Fid is the file ID assigned to the file and returned to the
// client. Pid is the process ID given by the client when the file
// was opened. Tid is a copy of the parent tree connect's Tid
// field. Uid is used to ensure that the client using a file handle
// is the same one that opened the file.
//
USHORT Fid;
USHORT Pid;
USHORT Tid;
USHORT Uid;
//
// WriteMpx is a WRITE_MPX_CONTEXT structure. It retains context
// about multiplexed write operations. This structure is not used
// on connectionless sessions.
//
WRITE_MPX_CONTEXT WriteMpx;
//
// FileMode tracks whether writethrough is enabled for this file
// object.
ULONG FileMode;
//
// MFCB points to the Master File Control Block for this file.
//
PMFCB Mfcb;
//
// Oplock information. The oplock IRP currently in progress, etc.
// The list entry for queueing the RFCB for oplock break processing
// is located in the block header.
//
PIRP Irp;
BOOLEAN OnOplockBreaksInProgressList;
//
// The oplock level to change to, if there is an oplock break
// in progress. Otherwise it is always NO_OPLOCK_BREAK_IN_PROGRESS.
//
UCHAR NewOplockLevel;
//
// This boolean indicates whether or an oplock granted open response
// need to be sent for this RFCB. If it is FALSE, and an oplock break
// request needs to be sent, the request must be deferred until after
// sending the open response.
//
// Access to these fields is synchronized using the MFCB lock.
//
BOOLEAN OpenResponseSent;
BOOLEAN DeferredOplockBreak;
//
// Pointer to the paged portion of the rfcb
//
PPAGED_RFCB PagedRfcb;
//
// CachedOpen is set if the RFCB has been cached after being
// closed by the client.
//
LIST_ENTRY CachedOpenListEntry;
BOOLEAN CachedOpen;
//
// See if this rfcb can be cached.
//
BOOLEAN IsCacheable;
//
// See if the file was accessed in the last scavenger update period.
// (This is used to update the session last access time).
//
BOOLEAN IsActive;
//
// Is it ok for us to do MPX writes to this RFCB?
//
BOOLEAN MpxWritesOk;
//
// Is this file a persistent handle?
//
#ifdef INCLUDE_SMB_PERSISTENT
BOOLEAN PersistentHandle;
#endif
//
// This event is used when the server needs to request an oplock II
// when the initial oplock request fails.
//
PKEVENT RetryOplockRequest;
//
// All RFCBs in the server are stored in a global list to support
// NetFileEnum. This field contains the LIST_ENTRY for the RFCB in
// the global list and a resume handle to support resuming
// enumerations.
//
ORDERED_LIST_ENTRY GlobalRfcbListEntry;
//
// GrantedAccess is the access allowed through this open. This
// GrantedAccess may allow less access than that given in the parent
// LFCB for compatibility mode opens.
//
ACCESS_MASK GrantedAccess;
//
// ShareAccess is the file sharing access specified when the file
// was opened.
//
ULONG ShareAccess;
//
// Current oplock state.
//
OPLOCK_STATE OplockState;
//
// Is it ok for us to do MPX reads to this RFCB?
//
BOOLEAN MpxReadsOk;
#ifdef SRVCATCH
BOOLEAN SrvCatch;
#endif
#ifdef SRVDBG_RFCBHIST
UCHAR HistoryIndex;
ULONG History[256];
#endif
#ifdef SLMDBG
ULONG NextTrace;
ULONG TraceWrapped;
ULONG WriteCount;
ULONG OperationCount;
RFCB_TRACE Trace[SLMDBG_TRACE_COUNT];
#endif
} RFCB, *PRFCB;
#ifdef SRVDBG_RFCBHIST
VOID UpdateRfcbHistory( PRFCB Rfcb, ULONG Event );
#else
#define UpdateRfcbHistory(_rfcb,_event)
#endif
#ifdef INCLUDE_SMB_PERSISTENT
typedef struct _BYTELOCK {
BLOCK_HEADER BlockHeader;
//
// Locks are linked into their parent RFCB's open list.
//
LIST_ENTRY RfcbListEntry;
PRFCB Rfcb;
//
// Information about the lock.
//
LARGE_INTEGER LockOffset;
LARGE_INTEGER LockLength;
BOOLEAN Exclusive;
//
// If the client has a persistent connection, here's the info for this
// record in the state file.
//
PERSISTENT_INFO; // persistent info
} BYTELOCK, *PBYTELOCK;
#endif
#ifdef SLMDBG
NTSTATUS
SrvValidateSlmStatus (
IN HANDLE StatusFile,
IN struct _WORK_CONTEXT *WorkContext,
OUT PULONG FileOffsetOfInvalidData
);
VOID
SrvReportCorruptSlmStatus (
IN PUNICODE_STRING StatusFile,
IN NTSTATUS Status,
IN ULONG Offset,
IN ULONG Operation,
IN PSESSION Session
);
VOID
SrvReportSlmStatusOperations (
IN PRFCB Rfcb,
IN BOOLEAN Force
);
VOID
SrvDisallowSlmAccess (
IN PUNICODE_STRING StatusFile,
IN HANDLE RootDirectory
);
VOID
SrvDisallowSlmAccessA (
IN PANSI_STRING StatusFile,
IN HANDLE RootDirectory
);
BOOLEAN
SrvIsSlmAccessDisallowed (
IN PUNICODE_STRING StatusFile,
IN HANDLE RootDirectory
);
BOOLEAN
SrvIsSlmStatus (
IN PUNICODE_STRING StatusFile
);
BOOLEAN
SrvIsTempSlmStatus (
IN PUNICODE_STRING StatusFile
);
#endif
//
// Each incoming (request) and outgoing (response) buffer is represented
// by a BUFFER structure. This descriptor describes the size of the
// buffer, its address, and a full and partial MDL that may be used
// to describe the buffer.
//
// *** The descriptor contains a pointer to the real buffer, which is
// normally allocated out of nonpaged pool. The descriptor itself
// may be allocated out of the FSP heap, although receive buffer
// descriptors are allocated from nonpaged pool, so the FSD
// read/write code can access them.
//
typedef struct _BUFFER {
PVOID Buffer;
CLONG BufferLength; // Length allocated to buffer
PMDL Mdl; // MDL describing entire buffer
PMDL PartialMdl; // Partial MDL for read/write/etc.
CLONG DataLength; // Length of data currently in buffer
ULONG Reserved; // Pad to quadword
} BUFFER, *PBUFFER;
#define MIN_SEND_SIZE 512
#define MAX_PARTIAL_BUFFER_SIZE 65535
//
// For each search request that is started (Find First or core Search),
// a search block is allocated. This is used to hold enough information
// that the search may be quickly restarted or rewound.
//
// Ths InUse field is protected by Connection->Lock--this lock must be
// held when accessing this field of the search block.
//
typedef struct _SEARCH {
BLOCK_HEADER BlockHeader;
HANDLE DirectoryHandle;
ULONG LastFileIndexReturned;
UNICODE_STRING SearchName;
UNICODE_STRING LastFileNameReturned;
LARGE_INTEGER LastUseTime;
LIST_ENTRY LastUseListEntry;
LIST_ENTRY HashTableEntry;
PSESSION Session;
PTREE_CONNECT TreeConnect;
ULONG SearchStorageType;
struct _DIRECTORY_CACHE *DirectoryCache;
USHORT NumberOfCachedFiles;
USHORT SearchAttributes;
SHORT CoreSequence;
SHORT TableIndex;
USHORT HashTableIndex;
USHORT Pid;
USHORT Flags2;
BOOLEAN Wildcards;
BOOLEAN InUse;
// WCHAR SearchNameData[SearchName.MaximumLength/2];
} SEARCH, *PSEARCH;
//
// Each pending transaction request (Transaction, Transaction2, and
// Ioctl) has a transaction block. It records information that is
// needed to stage input and output data across multiple SMBs.
//
// *******************************************************************
// * *
// * DO NOT CHANGE THIS STRUCTURE WITHOUT CHANGING THE CORRESPONDING *
// * STRUCTURE IN net\inc\xstypes.h! *
// * *
// *******************************************************************
//
typedef struct _TRANSACTION {
//
// *** NOTE: The reference count field in the transaction block
// header is not used! Instead, the reference count is
// in the NonpagedHeader structure.
//
BLOCK_HEADER BlockHeader;
PNONPAGED_HEADER NonpagedHeader;
//
// The connection, session, and tree connect pointers are referenced
// pointers if and only if Inserted is TRUE. Otherwise, they are
// simply copies of the work context block's pointers.
//
PCONNECTION Connection;
PSESSION Session;
PTREE_CONNECT TreeConnect;
LIST_ENTRY ConnectionListEntry;
UNICODE_STRING TransactionName; // not used if Transaction2
ULONG StartTime;
ULONG Timeout;
CLONG cMaxBufferSize; // if needed we stash this here
//
// The following pointers point into either the trailing portion
// of the transaction block or the last received SMB.
//
// *** ALL information in buffers pointed to by these parameters
// should ALWAYS be in little-endian format. Always use the
// macros defined in srvmacro.h (SmbGetAlignedUshort, etc.) to
// read from or write into these buffers.
//
PSMB_USHORT InSetup;
PSMB_USHORT OutSetup;
PCHAR InParameters;
PCHAR OutParameters;
PCHAR InData;
PCHAR OutData;
//
// *** Data in all the remaining fields of the transaction block are
// in native format, so no special macros should be used, except
// when copying data to/from the actual SMB.
//
CLONG SetupCount; // amount received (all in first buffer)
CLONG MaxSetupCount; // max that can be sent back
CLONG ParameterCount; // amount received or sent
CLONG TotalParameterCount; // amount expected
CLONG MaxParameterCount; // max that can be sent back
CLONG DataCount; // amount received or sent
CLONG TotalDataCount; // amount expected
CLONG MaxDataCount; // max that can be sent back
USHORT Category; // Ioctl function category
USHORT Function; // Nt Transaction or ioctl function code
//
// The SMB data and paramters may or may not be copied to the
// transaction buffer. If they are not copied, they are read
// and/or written directly into an SMB buffer.
//
// Setup words are never copied.
//
BOOLEAN InputBufferCopied; // if FALSE input buffer is in SMB
BOOLEAN OutputBufferCopied; // if FALSE output buffer is in SMB
BOOLEAN OutDataAllocated; // if TRUE OutData buffer has been separately allocated
USHORT Flags;
USHORT Tid;
USHORT Pid;
USHORT Uid;
USHORT OtherInfo;
HANDLE FileHandle; // Used only for CallNamedPipe processing
PFILE_OBJECT FileObject; // Used only for CallNamedPipe processing
//
// The following fields are used while the response is being sent.
//
CLONG ParameterDisplacement;
CLONG DataDisplacement;
//
// PipeRequest is set for named pipe transactions. RemoteApiRequest
// is set for remote API requests.
//
BOOLEAN PipeRequest;
BOOLEAN RemoteApiRequest;
//
// The following boolean is TRUE if the transaction has been inserted
// on the connection's transaction list. It will be FALSE when the
// transaction can be handled using a single SMB exchange.
//
BOOLEAN Inserted;
//
// This boolean is TRUE if the transaction is in the state where
// it is waiting for a transaction secondary request to come in
// to acknowledge the receipt of the previous piece of a multipiece
// transaction response.
//
BOOLEAN MultipieceIpxSend;
//
// This boolean is TRUE if all of the transaction data has been received
// and the transaction has been scheduled for execution.
//
BOOLEAN Executing;
//
// The main part of the transaction block is trailed by transaction
// name data and possibly setup words and parameter and data bytes.
//
} TRANSACTION, *PTRANSACTION;
//
// Each pending blocking open request has a BLOCKING_OPEN block. This
// block contains all the info needed to make the call into the file
// system.
typedef struct _BLOCKING_OPEN {
BLOCK_HEADER BlockHeader;
PMFCB Mfcb;
PIO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING RelativeName;
PVOID EaBuffer;
CLONG EaLength;
LARGE_INTEGER AllocationSize;
ULONG DesiredAccess;
ULONG FileAttributes;
ULONG ShareAccess;
ULONG CreateDisposition;
ULONG CreateOptions;
BOOLEAN CaseInsensitive;
} BLOCKING_OPEN, *PBLOCKING_OPEN;
//
// SRV_TIMER is used for timed operations. The server maintains a pool
// of these structures.
//
typedef struct _SRV_TIMER {
SINGLE_LIST_ENTRY Next;
KEVENT Event;
KTIMER Timer;
KDPC Dpc;
} SRV_TIMER, *PSRV_TIMER;
typedef struct _IPX_CLIENT_ADDRESS {
TA_IPX_ADDRESS IpxAddress;
TDI_CONNECTION_INFORMATION Descriptor;
IPX_DATAGRAM_OPTIONS DatagramOptions;
} IPX_CLIENT_ADDRESS, *PIPX_CLIENT_ADDRESS;
//
// The state for an I/O request is maintained in a Work Context Block.
// Various fields in the block are filled in or not depending upon the
// request. When a worker thread removes a work item from the FSP work
// queue, it uses the context block, and items pointed to by the
// context block, to determine what to do.
//
// *** Not all of the back pointers have to be here, because a tree
// connect points to a session, which points to a connection, which
// points to an endpoint, etc. However, depending on the operation
// and the state of the operation, we may have a connection pointer
// but no session pointer, etc. So we maintain all of the
// pointers.
//
// *** Any changes to the first 2 elements of this structure must be
// made in concert with the SPECIAL_WORK_ITEM structure in srvtypes.h
//
typedef struct _WORK_CONTEXT {
//
// The list entry in the block header is used to queue the WC for to
// the nonblocking or blocking worker thread work queue. The
// nonblocking work queue also contains RFCBs.
//
// *** Note that this is an unnamed field, so that its elements can
// can be referenced directly. The field names defined in
// QUEUEABLE_BLOCK_HEADER cannot be used elsewhere in this
// block.
//
// Timestamp (in the block header) is used to calculate the total
// time this work context block was on the work queue.
//
// When the work context block is not in use, Timestamp is used to
// record the time at which the block was inserted on the free list.
// This is used to determine when dynamically-allocated work context
// blocks have been idle long enough justify their deletion.
//
// FspRestartRoutine (in the block header) is the routine that is to
// be called by worker thread when the work item is dequeued from
// the work queue.
//
QUEUEABLE_BLOCK_HEADER ; // must be first element
//
// This is the WORK_QUEUE to queue on if we're doing nonblocking work
// It will always point to a valid WORK_QUEUE, even if we're doing
// blocking work.
//
PWORK_QUEUE CurrentWorkQueue;
//
// The free list this should be returned to when work is done
//
PSLIST_HEADER FreeList;
//
// FsdRestartRoutine is the routine that is to be called by the
// FSD's I/O completion routine. This routine can do more
// processing or queue the work item to the FSP. In this case, when
// a worker thread removes the item from the work queue, it calls
// FspRestartRoutine.
//
PRESTART_ROUTINE FsdRestartRoutine;
//
// Linkage field for the in-progress work item list.
//
LIST_ENTRY InProgressListEntry;
//
// Pointers to various structures that might be used.
// These pointers are all referenced pointers. It is
// the responsibility of the SMB processing routines to
// dereference and clear these pointers when they are no
// longer needed.
//
PRFCB Rfcb;
PSHARE Share;
PSESSION Session;
PTREE_CONNECT TreeConnect;
//
// These are gathered in one place to facilitate quick zeroing
// of their values when the work context is finished
//
struct _WorkContextZeroBeforeReuse {
//
// unreferenced pointer to the endpoint structure for
// this work context. Filled in by SrvRestartReceive and
// available to all SMB processing routines.
//
// Endpoint must be the first element in this structure. See
// INITIALIZE_WORK_CONTEXT in srvmacro.h if changed.
//
PENDPOINT Endpoint; // not a referenced pointer
//
// referenced pointer to the connection structure for this
// this work context. Filled in by SrvRestartReceive and
// available to all SMB processing routines.
//
PCONNECTION Connection; // a reference pointer
//
// The number of times this SMB has been queued to a worker thread
// for processing.
//
ULONG ProcessingCount;
//
// This is a random collection of flags that are needed to steer
// the WorkItem
//
struct {
//
// Can the processing of the current SMB block?
//
ULONG BlockingOperation : 1;
//
// UsingExtraSmbBuffer is TRUE if this work context uses the an extra SMB
// buffer.
//
ULONG UsingExtraSmbBuffer : 1;
//
// Did this Work Item cause a successful oplock open to occur?
//
ULONG OplockOpen : 1;
//
// If we got an ACCESS_DENIED error when opening a file, was it because
// of share ACL checking?
ULONG ShareAclFailure : 1;
//
// Should the WorkContext be queued to the head of the list?
//
ULONG QueueToHead : 1;
//
// Even if security signatures are enabled, do not generate a signature for
// this response.
//
ULONG NoResponseSmbSecuritySignature : 1;
//
// The indicated message exceeds the SMB buffer size. This is allowed
// only for specific SMB(s)
//
ULONG LargeIndication: 1;
#if DBG_STUCK
//
// Do not include this operation in the StuckOperation catching logic
// which is in the scavenger
//
ULONG IsNotStuck : 1;
#endif
};
// For SnapShot usage
LARGE_INTEGER SnapShotTime;
};
//
// Pointers to allocated buffers. RequestBuffer is the buffer into
// which the SMB is read. ResponseBuffer is the buffer into which
// the response is written.
//
// *** Currently, ResponseBuffer is always the same as
// RequestBuffer. We have separate pointers in order to reduce
// dependence on this being the case.
//
PBUFFER RequestBuffer;
PBUFFER ResponseBuffer;
//
// SMB processing pointers. These are pointers into the request
// buffer. They are maintained in the work context block in support
// of SMB processors that do asynchronous I/O.
//
// Separate request and response parameter pointers are maintained
// to make AndX processing simpler and more efficient. RequestHeader
// is normally the same as ResponseHeader -- both are normally the
// same as RequestBuffer.Buffer. SMB processing code must not depend
// on this -- it must not assume the the request and response buffers
// are the same, nor can it assume that they are different. Special
// rules around AndX SMBs do allow them to assume that the response
// to one command will not overwrite the next request.
//
PSMB_HEADER RequestHeader;
PVOID RequestParameters;
PSMB_HEADER ResponseHeader;
PVOID ResponseParameters;
//
// Pointer to the IRP associated with this work item.
//
PIRP Irp;
//
// StartTime stores the time at which processing of the current
// request began so that the turnaround time may be calculated.
//
ULONG StartTime;
//
// The PartOfInitialAllocation boolean indicates whether this work
// item is part of the block of work items allocated at server
// startup (see blkwork.c\SrvAllocateInitialWorkItems). Such work
// items cannot be deleted during server operation. A work item
// that is dynamically allocated in response to server load does not
// have this bit set, and is a candidate for deletion when the
// server's load decreases.
//
ULONG PartOfInitialAllocation;
//
// The following field contadins the command code of the next
// command to be processed in an SMB. The SMB processing
// initializer and chained (AndX) SMB command processors load this
// field prior to calling or returning to SrvProcessSmb.
//
UCHAR NextCommand;
//
// ClientAddress is used when receiving or sending over IPX.
//
PIPX_CLIENT_ADDRESS ClientAddress;
//
// Spin lock protecting reference count.
//
KSPIN_LOCK SpinLock;
//
// The security signature index for the request
//
ULONG SmbSecuritySignatureIndex;
//
// The security signature index for the response
//
ULONG ResponseSmbSecuritySignatureIndex;
//
// The following union is used to hold request-specific state while
// a response is being sent or while waiting for more data.
//
union {
//
// RemainingEchoCount is used when processing the Echo SMB.
//
USHORT RemainingEchoCount;
//
// Structure used for lock processing. This structure is
// currently used when processing the Lock, LockingAndX, and the
// LockAndRead SMBs.
//
struct {
//
// LockRange is used when processing the LockingAndX SMB. It is
// really either a PLOCKING_ANDX_RANGE, or a PNTLOCKING_ANDX_RANGE
// not just a PVOID.
//
PVOID LockRange;
//
// Timer is a timer and DPC used to timeout lock requests.
//
PSRV_TIMER Timer;
#ifdef INCLUDE_SMB_PERSISTENT
LARGE_INTEGER Offset; // offset for this lock
LARGE_INTEGER Length; // length of this lock
BOOLEAN Exclusive; // is this lock exclusive?
#endif
} Lock;
//
// Transaction is used when processing the Transaction[2] SMBs.
// Or when processing a write and X SMB.
//
PTRANSACTION Transaction;
//
// MdlIo is used when processing the ReadRaw or WriteRaw
// SMBs when "MDL read" or "MDL write" is used. It
// retains the status of the response send while the MDL is
// returned to the file system.
//
struct {
IO_STATUS_BLOCK IoStatus;
ULONG IrpFlags;
} MdlIo;
//
// LastWriteTime is used when processing any Read or Write SMB
// that uses RestartChainedClose as a restart routine. This
// field contains the new last write time to set for the file.
//
ULONG LastWriteTime;
//
// CurrentTableIndex is used when processing the Flush SMB. It
// retains the current index into the connection's file table
// when an asynchronous flush is in progress.
//
LONG CurrentTableIndex;
//
// ReadRaw is used when processing the Read Block Raw SMB.
// Offset is the file offset of the read. SavedResponseBuffer
// points to the original SMB response buffer descriptor, which
// is temporarily replaced by a descriptor for the raw read
// buffer. MdlRead indicates whether an MDL read was used,
// rather than a Copy read.
//
struct {
union {
//
// Used for non named pipe reads
//
LARGE_INTEGER Offset;
ULONG Length;
//
// Used only for named pipe reads
//
PFILE_PIPE_PEEK_BUFFER PipePeekBuffer;
} ReadRawOtherInfo;
PBUFFER SavedResponseBuffer;
BOOLEAN MdlRead;
} ReadRaw;
//
// WriteRaw is used when processing the Write Block Raw SMB.
// FinalResponseBuffer points to the buffer allocated to contain
// the final response SMB, if writethrough mode was specified.
// Offset is the file offset of the write. ImmediateLength is
// the amount of write data that was sent with the request SMB.
// Pid is the PID of the writer, used to form the lock key on
// the write. FileObject is a pointer to the file object copied
// from the LFCB. (Pid is not used when MDL write is used;
// FileObject is not used when copy write is used.)
//
struct {
struct _WORK_CONTEXT *RawWorkContext;
} WriteRawPhase1;
struct {
LARGE_INTEGER Offset;
ULONG Length;
PVOID FinalResponseBuffer;
CLONG ImmediateLength;
PMDL FirstMdl;
//PFILE_OBJECT FileObject;
USHORT Pid;
BOOLEAN MdlWrite;
BOOLEAN ImmediateWriteDone;
} WriteRaw;
//
// ReadAndXCompressed is the structure used when handling
// compressed ReadAndX
//
struct {
LARGE_INTEGER ReadOffset; // original read offset
ULONG ReadLength; // original read length
ULONG CompressedInfoLength;
FSRTL_AUXILIARY_BUFFER Aux;
} ReadAndXCompressed;
//
// ReadAndX is the structure used when handling the ReadAndX
// SMB.
//
struct {
LARGE_INTEGER ReadOffset;
ULONG ReadLength;
PCHAR ReadAddress;
union {
struct {
PFILE_PIPE_PEEK_BUFFER PipePeekBuffer;
ULONG LastWriteTimeInSeconds; // used if Close is chained
};
struct { // used for ReadLength > negotiated size
PBYTE Buffer; // allocated paged pool, if copy read
PMDL SavedMdl;
PMDL CacheMdl;
USHORT PadCount;
BOOLEAN MdlRead;
};
};
} ReadAndX;
#define READX_BUFFER_OFFSET (sizeof(SMB_HEADER) + FIELD_OFFSET(RESP_READ_ANDX, Buffer) )
//
// WriteAndX is the structure used when handling the flavor of WriteAndX that
// exceeds the negotiated buffer size
//
struct {
ULONG CurrentWriteLength; // amount of data that was written this time
LARGE_INTEGER Offset; // file offset for this piece of the write
ULONG RemainingWriteLength; // amount of data remaining to be read from xport
ULONG Key; // lock key for the operation
PCHAR WriteAddress; // address in buffer for the data
ULONG BufferLength; // Maximum buffer length in this WorkContext
NTSTATUS FinalStatus; // Final status of the operation
PMDL MdlAddress; // File MDL if MdlWrite == TRUE
BOOLEAN InitialComplete; // TRUE if we have written first part to the file
} WriteAndX;
//
// WriteC is used when we are doing compressed writes
//
struct {
LARGE_INTEGER Offset; // File offset for this piece of the write
ULONG Key; // Lock key for the operation
ULONG CdiLength; // COMPRESSED_DATA_INFO length if compressed write
ULONG CompressedDataLength; // Length of compressed data
ULONG UncompressedDataLength; // Uncompressed length of the write
PCOMPRESSED_DATA_INFO Cdi; // The compressed data info descriptor for this write
ULONG InitialFragmentSize; // Amount of CompressedData in initial receive
FSRTL_AUXILIARY_BUFFER Aux;
PMDL Mdl; // Mdl we are using for compressed writes
BOOLEAN MdlCompleted; // Have we called MdlWriteCompleteCompressed yet?
PFAST_IO_MDL_WRITE_COMPLETE_COMPRESSED MdlWriteCompleteCompressed;
PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
PBYTE CompressedBuffer; // In case the PrepareMdlWrite failed!
PBYTE UncompressedBuffer;
} WriteC;
//
// ReadMpx is the structure used when handling the ReadMpx SMB, unless
// we have a SmartCard accelerating our reads. In this case,
// SmartCardRead is used.
//
struct {
ULONG Offset;
USHORT FragmentSize;
USHORT RemainingLength;
ULONG ReadLength;
BOOLEAN MdlRead;
UCHAR Unused;
USHORT CurrentMdlOffset; // logically part of MDL read struct below
union {
struct {
PVOID MpxBuffer;
PMDL MpxBufferMdl;
PCHAR NextFragmentAddress;
} ;
struct {
PMDL FirstMdl;
PMDL CurrentMdl;
} ;
} ;
} ReadMpx;
//
// SmartCardRead is used to handle direct host read requests if we have
// a Smart Card accelerating the particular request.
//
struct {
PDEVICE_OBJECT DeviceObject;
PFAST_IO_MDL_READ_COMPLETE MdlReadComplete;
} SmartCardRead;
//
// WriteMpx is the structure used when handling the WriteMpx SMB.
//
struct {
ULONG Offset;
USHORT WriteLength;
USHORT Mid;
BOOLEAN FirstPacketOfGlom;
PVOID Buffer;
ULONG ReceiveDatagramFlags;
PVOID TransportContext;
PMDL DataMdl;
} WriteMpx;
struct {
LARGE_INTEGER CacheOffset;
ULONG WriteLength;
PMDL CacheMdl;
} WriteMpxMdlWriteComplete;
//
// FastTransactNamedPipe is used when handling a small named pipe
// transaction.
//
struct {
PSMB_USHORT OutSetup;
PCHAR OutParam;
PCHAR OutData;
} FastTransactNamedPipe;
#ifdef INCLUDE_SMB_PERSISTENT
struct {
ULONG ResumeSmbStatus;
PRESTART_ROUTINE FsdRestartRoutine;
PRESTART_ROUTINE FspRestartRoutine;
} MakePersistent;
#endif
} Parameters;
// !!! check whether the compiler leaves a dword gap here!
//
// The following union holds state information about SMBs in progress
// waiting for an oplock break. It is kept separate from the Parameters
// union, since information from both is needed to process some SMBs.
//
union {
//
// Open is the structure used when handling the Open,
// OpenAndX, Open2, Create, or CreateTemporary SMB.
//
struct {
PRFCB Rfcb;
PFILE_FULL_EA_INFORMATION NtFullEa;
ULONG EaErrorOffset;
//
// The Irp used to open the file is the same Irp used to handle
// the oplock processing. This can cause us to lose the original
// iosb->Information. Save it here.
//
ULONG_PTR IosbInformation;
//
// If TRUE, the file was opened only in order to get a handle
// so that we can wait for an oplock to break. This handle will
// be immediately closed, and the open will be retried with the
// user requested access.
//
BOOLEAN TemporaryOpen;
} Open;
//
// FileInformation is the structure used when handling the
// QueryInformation, SetInformation, QueryPathInformation,
// or SetPathInformation SMB.
//
struct {
HANDLE FileHandle;
} FileInformation;
//
// LockLength is used to contain the length of a byte range
// lock since the IRP stack location has no room to hold it.
LARGE_INTEGER LockLength;
//
// StartSend is used by SrvStartSend when queueing a work item
// to the FSP for handling by the SmbTrace logic.
//
struct {
PRESTART_ROUTINE FspRestartRoutine;
ULONG SendLength;
} StartSend;
} Parameters2;
//
// This field is used when the current operation is blocked waiting
// for an oplock break to occur.
//
struct _WAIT_FOR_OPLOCK_BREAK *WaitForOplockBreak;
union {
//
// where we keep the actual client address data.
//
IPX_CLIENT_ADDRESS ClientAddressData;
//
// For a VC-based client, this is the amount of available data if
// LargeIndication is set (above)
//
ULONG BytesAvailable;
};
struct {
LARGE_INTEGER G_StartTime;
ULONG ElapseKCPU;
ULONG ElapseUCPU;
ULONG ClientAddr;
PFILE_OBJECT FileObject;
};
ULONG KCPUStart;
ULONG UCPUStart;
UCHAR PreviousSMB;
UCHAR bAlreadyTrace;
USHORT FileNameSize;
WCHAR strFileName[1024];
#if DBG_STUCK
//
// Time at which this work context was allocated for this current
// unit of work. This time is examined by debugging code in the
// scavenger to help find operations which are taking too long
// to complete.
//
LARGE_INTEGER OpStartTime;
#endif
} WORK_CONTEXT, *PWORK_CONTEXT;
//
// Structure used to maintain information about a thread waiting for
// an oplock break.
//
typedef struct _WAIT_FOR_OPLOCK_BREAK {
BLOCK_HEADER BlockHeader;
LIST_ENTRY ListEntry;
LARGE_INTEGER TimeoutTime;
PIRP Irp;
WAIT_STATE WaitState;
} WAIT_FOR_OPLOCK_BREAK, *PWAIT_FOR_OPLOCK_BREAK;
//
// Block manager routines
//
//
// Buffer routines
//
VOID
SrvAllocateBuffer (
OUT PBUFFER *Buffer,
IN CLONG BufferLength
);
VOID
SrvFreeBuffer (
IN PBUFFER Buffer
);
//
// Connection routines
//
VOID
SrvAllocateConnection (
OUT PCONNECTION *Connection
);
VOID
SrvCloseConnection (
IN PCONNECTION Connection,
IN BOOLEAN RemoteDisconnect
);
VOID
SrvCloseConnectionsFromClient(
IN PCONNECTION Connection,
IN BOOLEAN OnlyIfNoSessions
);
VOID
SrvCloseFreeConnection (
IN PCONNECTION Connection
);
VOID
SrvDereferenceConnection (
IN PCONNECTION Connection
);
VOID
SrvFreeConnection (
IN PCONNECTION Connection
);
#if DBG
NTSTATUS
SrvQueryConnections (
OUT PVOID Buffer,
IN ULONG BufferLength,
OUT PULONG BytesWritten
);
#endif
//
// Endpoint routines
//
VOID
SrvAllocateEndpoint (
OUT PENDPOINT *Endpoint,
IN PUNICODE_STRING NetworkName,
IN PUNICODE_STRING TransportName,
IN PANSI_STRING TransportAddress,
IN PUNICODE_STRING DomainName
);
BOOLEAN SRVFASTCALL
SrvCheckAndReferenceEndpoint (
IN PENDPOINT Endpoint
);
VOID
SrvCloseEndpoint (
IN PENDPOINT Endpoint
);
VOID SRVFASTCALL
SrvDereferenceEndpoint (
IN PENDPOINT Endpoint
);
VOID
SrvFreeEndpoint (
IN PENDPOINT Endpoint
);
VOID
SrvReferenceEndpoint (
IN PENDPOINT Endpoint
);
BOOLEAN
SrvFindNamedEndpoint (
IN PUNICODE_STRING ServerName,
IN PBOOLEAN RemapPipeNames OPTIONAL
);
VOID
EmptyFreeConnectionList (
IN PENDPOINT Endpoint
);
PCONNECTION
WalkConnectionTable (
IN PENDPOINT Endpoint,
IN PUSHORT Index
);
//
// Local File Control Block routines
//
VOID
SrvAllocateLfcb (
OUT PLFCB *Lfcb,
IN PWORK_CONTEXT WorkContext
);
VOID
SrvCloseLfcb (
IN PLFCB Lfcb
);
VOID
SrvDereferenceLfcb (
IN PLFCB Lfcb
);
VOID
SrvFreeLfcb (
IN PLFCB Lfcb,
IN PWORK_QUEUE queue
);
VOID
SrvReferenceLfcb (
IN PLFCB Lfcb
);
//
// Master File Control Block routines
//
PMFCB
SrvCreateMfcb(
IN PUNICODE_STRING FileName,
IN PWORK_CONTEXT WorkContext,
IN ULONG HashValue
);
PMFCB
SrvFindMfcb(
IN PUNICODE_STRING FileName,
IN BOOLEAN CaseInsensitive,
OUT PSRV_LOCK *Lock,
OUT PULONG HashValue,
IN PWORK_CONTEXT WorkContext
);
VOID
SrvDereferenceMfcb (
IN PMFCB Mfcb
);
VOID
SrvFreeMfcb (
IN PMFCB Mfcb
);
VOID
SrvUnlinkLfcbFromMfcb (
IN PLFCB Lfcb
);
//
// Remote File Control Block routines
//
VOID SRVFASTCALL
SrvAllocateRfcb (
OUT PRFCB *Rfcb,
IN PWORK_CONTEXT WorkContext
);
BOOLEAN SRVFASTCALL
SrvCheckAndReferenceRfcb (
IN PRFCB Rfcb
);
VOID SRVFASTCALL
SrvCloseRfcb (
IN PRFCB Rfcb
);
VOID
SrvCloseRfcbsOnLfcb (
PLFCB Lfcb
);
VOID
SrvCloseRfcbsOnSessionOrPid (
IN PSESSION Session,
IN PUSHORT Pid OPTIONAL
);
VOID
SrvCloseRfcbsOnTree (
PTREE_CONNECT TreeConnect
);
VOID
SrvCompleteRfcbClose (
IN PRFCB Rfcb
);
VOID SRVFASTCALL
SrvDereferenceRfcb (
IN PRFCB Rfcb
);
VOID SRVFASTCALL
SrvFreeRfcb (
IN PRFCB Rfcb,
IN PWORK_QUEUE queue
);
VOID SRVFASTCALL
SrvReferenceRfcb (
IN PRFCB Rfcb
);
BOOLEAN
SrvFindCachedRfcb (
IN PWORK_CONTEXT WorkContext,
IN PMFCB Mfcb,
IN ACCESS_MASK DesiredAccess,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN OPLOCK_TYPE RequestedOplockType,
OUT PNTSTATUS Status
);
VOID
SrvCloseCachedRfcb (
IN PRFCB Rfcb,
IN KIRQL OldIrql
);
VOID
SrvCloseCachedRfcbsOnConnection (
IN PCONNECTION Connection
);
VOID
SrvCloseCachedRfcbsOnLfcb (
IN PLFCB Lfcb
);
ULONG
SrvCountCachedRfcbsForTid(
PCONNECTION connection,
USHORT Tid
);
ULONG
SrvCountCachedRfcbsForUid(
PCONNECTION connection,
USHORT Uid
);
//
// Search Block routines
//
typedef
BOOLEAN
(*PSEARCH_FILTER_ROUTINE) (
IN PSEARCH Search,
IN PVOID FunctionParameter1,
IN PVOID FunctionParameter2
);
VOID
SrvAllocateSearch (
OUT PSEARCH *Search,
IN PUNICODE_STRING SearchName,
IN BOOLEAN IsCoreSearch
);
VOID
SrvCloseSearch (
IN PSEARCH Search
);
VOID
SrvCloseSearches (
IN PCONNECTION Connection,
IN PSEARCH_FILTER_ROUTINE SearchFilterRoutine,
IN PVOID FunctionParameter1,
IN PVOID FunctionParameter2
);
VOID
SrvDereferenceSearch (
IN PSEARCH Search
);
VOID
SrvFreeSearch (
IN PSEARCH Search
);
VOID
SrvReferenceSearch (
IN PSEARCH Search
);
BOOLEAN
SrvSearchOnDelete(
IN PSEARCH Search,
IN PUNICODE_STRING DirectoryName,
IN PTREE_CONNECT TreeConnect
);
BOOLEAN
SrvSearchOnPid(
IN PSEARCH Search,
IN USHORT Pid,
IN PVOID Dummy
);
BOOLEAN
SrvSearchOnSession(
IN PSEARCH Search,
IN PSESSION Session,
IN PVOID Dummy
);
BOOLEAN
SrvSearchOnTreeConnect(
IN PSEARCH Search,
IN PTREE_CONNECT TreeConnect,
IN PVOID Dummy
);
VOID
SrvForceTimeoutSearches(
IN PCONNECTION Connection
);
ULONG
SrvTimeoutSearches(
IN PLARGE_INTEGER SearchCutoffTime OPTIONAL,
IN PCONNECTION Connection,
IN BOOLEAN OnlyTimeoutOneBlock
);
VOID
RemoveDuplicateCoreSearches(
IN PPAGED_CONNECTION PagedConnection
);
VOID
SrvAddToSearchHashTable(
IN PPAGED_CONNECTION PagedConnection,
IN PSEARCH Search
);
//
// Cached directory routines
//
BOOLEAN
SrvIsDirectoryCached (
IN PWORK_CONTEXT WorkContext,
IN PUNICODE_STRING DirectoryName
);
VOID
SrvCacheDirectoryName (
IN PWORK_CONTEXT WorkContext,
IN PUNICODE_STRING DirectoryName
);
VOID
SrvRemoveCachedDirectoryName (
IN PWORK_CONTEXT WorkContext,
IN PUNICODE_STRING DirectoryName
);
VOID
SrvCloseCachedDirectoryEntries (
IN PCONNECTION Connection
);
//
// Session routines
//
VOID
SrvAllocateSession (
OUT PSESSION *Session,
IN PUNICODE_STRING UserName,
IN PUNICODE_STRING Domain
);
BOOLEAN SRVFASTCALL
SrvCheckAndReferenceSession (
IN PSESSION Session
);
VOID
SrvCloseSession (
IN PSESSION Session
);
VOID
SrvCloseSessionsOnConnection (
IN PCONNECTION Connection,
IN PUNICODE_STRING UserName OPTIONAL
);
VOID SRVFASTCALL
SrvDereferenceSession (
IN PSESSION Session
);
VOID
SrvFreeSession (
IN PSESSION Session
);
//
// Smb Security Signature Routines
//
BOOLEAN SRVFASTCALL
SrvCheckSmbSecuritySignature(
IN PWORK_CONTEXT WorkContext
);
VOID SRVFASTCALL
SrvAddSmbSecuritySignature(
IN OUT PWORK_CONTEXT WorkContext,
IN PMDL Mdl,
IN ULONG SendLength
);
VOID SRVFASTCALL
SrvInitializeSmbSecuritySignature(
IN OUT PCONNECTION Connection,
IN PUCHAR SessionKey,
IN PUCHAR ChallengeResponse,
IN ULONG ChallengeResponseLength
);
//
// Share routines
//
VOID
SrvAllocateShare (
OUT PSHARE *Share,
IN PUNICODE_STRING ShareName,
IN PUNICODE_STRING NtPathName,
IN PUNICODE_STRING DosPathName,
IN PUNICODE_STRING Remark,
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN PSECURITY_DESCRIPTOR FileSecurityDescriptor OPTIONAL,
IN SHARE_TYPE ShareType
);
VOID
SrvCloseShare (
IN PSHARE Share
);
VOID
SrvDereferenceShare (
IN PSHARE Share
);
VOID
SrvDereferenceShareForTreeConnect (
PSHARE Share
);
VOID
SrvFreeShare (
IN PSHARE Share
);
VOID
SrvReferenceShare (
IN PSHARE Share
);
NTSTATUS
SrvReferenceShareForTreeConnect (
PSHARE Share
);
//
// Table routines
//
VOID
SrvAllocateTable (
IN PTABLE_HEADER TableHeader,
IN ULONG NumberOfEntries,
IN BOOLEAN Nonpaged
);
#define SrvFreeTable( _table ) { \
if ( (_table)->Nonpaged ) { \
DEALLOCATE_NONPAGED_POOL( (_table)->Table ); \
} else { \
FREE_HEAP( (_table)->Table ); \
} \
DEBUG (_table)->Table = NULL; \
DEBUG (_table)->TableSize = -1; \
DEBUG (_table)->FirstFreeEntry = -1; \
DEBUG (_table)->LastFreeEntry = -1; \
}
BOOLEAN
SrvGrowTable (
IN PTABLE_HEADER TableHeader,
IN ULONG NumberOfNewEntries,
IN ULONG MaxNumberOfEntries,
OUT NTSTATUS* pStatus
);
VOID
SrvRemoveEntryTable (
IN PTABLE_HEADER TableHeader,
IN USHORT Index
);
//
// Transaction routines
//
VOID
SrvAllocateTransaction (
OUT PTRANSACTION *Transaction,
OUT PVOID *TrailingBytes,
IN PCONNECTION Connection,
IN CLONG TrailingByteCount,
IN PVOID TransactionName,
IN PVOID EndOfSourceBuffer OPTIONAL,
IN BOOLEAN SourceIsUnicode,
IN BOOLEAN RemoteApiRequest
);
VOID
SrvCloseTransaction (
IN PTRANSACTION Transaction
);
VOID
SrvCloseTransactionsOnSession (
PSESSION Session
);
VOID
SrvCloseTransactionsOnTree (
PTREE_CONNECT TreeConnect
);
VOID
SrvDereferenceTransaction (
IN PTRANSACTION Transaction
);
VOID
SrvFreeTransaction (
IN PTRANSACTION Transaction
);
PTRANSACTION
SrvFindTransaction (
IN PCONNECTION Connection,
IN PSMB_HEADER Header,
IN USHORT Fid OPTIONAL
);
BOOLEAN
SrvInsertTransaction (
IN PTRANSACTION Transaction
);
//
// Tree connect routines
//
VOID
SrvAllocateTreeConnect (
OUT PTREE_CONNECT *TreeConnect,
IN PUNICODE_STRING ServerName OPTIONAL
);
BOOLEAN SRVFASTCALL
SrvCheckAndReferenceTreeConnect (
IN PTREE_CONNECT TreeConnect
);
VOID
SrvCloseTreeConnect (
IN PTREE_CONNECT TreeConnect
);
VOID SRVFASTCALL
SrvDereferenceTreeConnect (
IN PTREE_CONNECT TreeConnect
);
VOID
SrvFreeTreeConnect (
IN PTREE_CONNECT TreeConnect
);
VOID
SrvDisconnectTreeConnectsFromSession (
PCONNECTION connection,
PSESSION Session
);
VOID
SrvCloseTreeConnectsOnShare (
IN PSHARE Share
);
//
// Work item routines (includes work contexts, buffers, MDLs, IRPs, etc)
//
NTSTATUS
SrvAllocateInitialWorkItems (
VOID
);
NTSTATUS
SrvAllocateNormalWorkItem (
OUT PWORK_CONTEXT *WorkContext,
IN PWORK_QUEUE queue
);
VOID
SrvAllocateRawModeWorkItem (
OUT PWORK_CONTEXT *WorkContext,
IN PWORK_QUEUE queue
);
PWORK_CONTEXT
SrvGetRawModeWorkItem (
VOID
);
VOID
SrvRequeueRawModeWorkItem (
IN PWORK_CONTEXT WorkContext
);
VOID SRVFASTCALL
SrvDereferenceWorkItem (
IN PWORK_CONTEXT WorkContext
);
VOID
SrvFsdDereferenceWorkItem (
IN PWORK_CONTEXT WorkContext
);
NTSTATUS
SrvAllocateExtraSmbBuffer (
IN OUT PWORK_CONTEXT WorkContext
);
VOID
SrvAllocateWaitForOplockBreak (
OUT PWAIT_FOR_OPLOCK_BREAK *WaitForOplockBreak
);
VOID
SrvDereferenceWaitForOplockBreak (
IN PWAIT_FOR_OPLOCK_BREAK WaitForOplockBreak
);
VOID
SrvFreeWaitForOplockBreak (
IN PWAIT_FOR_OPLOCK_BREAK WaitForOplockBreak
);
VOID
SrvOplockWaitTimeout(
IN PWAIT_FOR_OPLOCK_BREAK WaitForOplockBreak
);
NTSTATUS
SrvCheckOplockWaitState(
IN PWAIT_FOR_OPLOCK_BREAK WaitForOplockBreak
);
NTSTATUS
SrvWaitForOplockBreak (
IN PWORK_CONTEXT WorkContext,
IN HANDLE FileHandle
);
NTSTATUS
SrvStartWaitForOplockBreak (
IN PWORK_CONTEXT WorkContext,
IN PRESTART_ROUTINE RestartRoutine,
IN HANDLE Handle OPTIONAL,
IN PFILE_OBJECT FileObject OPTIONAL
);
VOID
SrvSendDelayedOplockBreak (
IN PCONNECTION Connection
);
VOID
SrvFreeInitialWorkItems (
VOID
);
VOID
SrvFreeNormalWorkItem (
IN PWORK_CONTEXT WorkContext
);
VOID
SrvFreeRawModeWorkItem (
IN PWORK_CONTEXT WorkContext
);
//
// Byte range lock routines
//
#ifdef INCLUDE_SMB_PERSISTENT
VOID
SrvAllocateLock (
OUT PBYTELOCK *Lock,
IN PRFCB Rfcb,
IN LARGE_INTEGER Offset,
IN LARGE_INTEGER Length,
IN BOOLEAN Exclusive
);
PBYTELOCK
SrvFindAndReferenceLock (
IN PRFCB Rfcb,
IN LARGE_INTEGER Offset,
IN LARGE_INTEGER Length,
IN BOOLEAN Exclusive
);
VOID
SrvCloseLock (
IN PBYTELOCK Lock,
IN BOOLEAN HaveMfcbLock
);
VOID
SrvCloseLocksOnRfcb (
IN PRFCB Rfcb
);
VOID SRVFASTCALL
SrvDereferenceLock (
IN PBYTELOCK Lock
);
#endif
//
// Timer routines
//
PSRV_TIMER
SrvAllocateTimer (
VOID
);
VOID
SrvCancelTimer (
IN PSRV_TIMER Timer
);
#define SrvDeleteTimer(_timer) DEALLOCATE_NONPAGED_POOL(_timer)
#define SrvFreeTimer(_timer) \
ExInterlockedPushEntrySList(&SrvTimerList, &(_timer)->Next, &GLOBAL_SPIN_LOCK(Timer))
VOID
SrvSetTimer (
IN PSRV_TIMER Timer,
IN PLARGE_INTEGER Timeout,
IN PKDEFERRED_ROUTINE TimeoutHandler,
IN PVOID Context
);
#if SRVDBG2
VOID
SrvInitializeReferenceHistory (
IN PBLOCK_HEADER Block,
IN LONG InitialReferenceCount
);
VOID
SrvUpdateReferenceHistory (
IN PBLOCK_HEADER Block,
IN PVOID Caller,
IN PVOID CallersCaller,
IN BOOLEAN IsDereference
);
VOID
SrvTerminateReferenceHistory (
IN PBLOCK_HEADER Block
);
#define INITIALIZE_REFERENCE_HISTORY(block) \
SrvInitializeReferenceHistory( \
&(block)->BlockHeader, \
((PBLOCK_HEADER)(block))->ReferenceCount \
)
#define UPDATE_REFERENCE_HISTORY(block,isdereference) \
{ \
PVOID caller, callerscaller; \
RtlGetCallersAddress( &caller, &callerscaller ); \
SrvUpdateReferenceHistory( \
&(block)->BlockHeader, \
caller, \
callerscaller, \
isdereference \
); \
}
#define TERMINATE_REFERENCE_HISTORY(block) \
SrvTerminateReferenceHistory( &(block)->BlockHeader )
#else
#define INITIALIZE_REFERENCE_HISTORY(block)
#define UPDATE_REFERENCE_HISTORY(block,isdereference)
#define TERMINATE_REFERENCE_HISTORY(block)
#endif // if SRVDBG2
#endif // ndef _SRVBLOCK