3723 lines
95 KiB
C
3723 lines
95 KiB
C
/*++ 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
|
||
|