mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3722 lines
95 KiB
3722 lines
95 KiB
/*++ 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; // "[email protected]"
|
|
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
|
|
|