737 lines
22 KiB
C
737 lines
22 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1989 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
mm.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module implements the memory managment routines for the SMB mini
|
||
|
redirector
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Balan Sethu Raman [SethuR] 7-March-1995
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
The SMB mini redirector manipulates entities which have very different usage
|
||
|
patterns. They range from very static entities ( which are allocated and freed
|
||
|
with a very low frequency ) to very dynamic entities.
|
||
|
|
||
|
The entities manipulated in the SMB mini redirector are SMBCE_SERVER, SMBCE_NET_ROOT,
|
||
|
SMBCE_VC, SMBCE_SESSION. These represent a connection to a server, a share on
|
||
|
a particular server, a virtual circuit used in the connection and a session
|
||
|
for a particular user.
|
||
|
|
||
|
These are not very dynamic, i.e., the allocation/deallocation is very infrequent.
|
||
|
The SMB_EXCHANGE and SMBCE_REQUEST map to the SMB's that are sent along that
|
||
|
a connection. Every file operation in turn maps to a certain number of calls
|
||
|
for allocationg/freeing exchanges and requests. Therefore it is imperative
|
||
|
that some form of scavenging/caching of recently freed entries be maintained
|
||
|
to satisfy requests quickly.
|
||
|
|
||
|
In the current implementation the exchanges and requests are implemented
|
||
|
using the zone allocation primitives.
|
||
|
|
||
|
The exchange allocation and free routines are currently implemented as wrappers
|
||
|
around the RxAllocate and RxFree routines. It would be far more efficient if
|
||
|
a look aside cache of some exchange instances are maintained.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include <exsessup.h>
|
||
|
#include <mssndrcv.h>
|
||
|
#include <vcsndrcv.h>
|
||
|
|
||
|
#ifdef ALLOC_PRAGMA
|
||
|
#pragma alloc_text(PAGE, SmbMmAllocateSessionEntry)
|
||
|
#pragma alloc_text(PAGE, SmbMmFreeSessionEntry)
|
||
|
#pragma alloc_text(PAGE, SmbMmAllocateServerTransport)
|
||
|
#pragma alloc_text(PAGE, SmbMmFreeServerTransport)
|
||
|
#pragma alloc_text(PAGE, SmbMmInit)
|
||
|
#pragma alloc_text(PAGE, SmbMmTearDown)
|
||
|
#endif
|
||
|
|
||
|
#define SMBMM_ZONE_ALLOCATION 0x10
|
||
|
|
||
|
// The memory management package addresses a number of concerns w.r.t debugging
|
||
|
// and performance. By centralizing all the allocation/deallocation routines to
|
||
|
// thsi one module it is possible to build up profiles regarding various data
|
||
|
// structures used by the connection engine. In addition debugging support is
|
||
|
// provided by thereading together all allocated objects of a particular type
|
||
|
// are threaded together in a linked list according to type.
|
||
|
//
|
||
|
// At any stage by inspecting these lists the currently active instances of a
|
||
|
// particular type can be enumerated.
|
||
|
//
|
||
|
// Each type handled by this module is provided with two routines, e.g., for
|
||
|
// server entries there are SmbMmInitializeEntry and SmbMmUninitializeEntry. The
|
||
|
// first routine is called before handing over a pointer of a newly created
|
||
|
// instance. This will ensure that the instance is in a wll known initial state.
|
||
|
// Similarly the second routine is called just before deallocating the pool
|
||
|
// associated with the instance. This helps enforce the necessary integrity
|
||
|
// constraints, e.g., all enclosed pointers must be NULL etc.
|
||
|
//
|
||
|
// The pool allocation/deallocation is handled by the following routines
|
||
|
//
|
||
|
// SmbMmAllocateObjectPool/SmbMmFreeObjectPool
|
||
|
//
|
||
|
// SmbMmAllocateExchange/SmbMmFreeExchange
|
||
|
//
|
||
|
// The Object allocation routines are split up into two parts so as to be able to
|
||
|
// handle the session allocationson par with other objects even though they are
|
||
|
// further subtyped.
|
||
|
//
|
||
|
// On debug builds additional pool is allocated and the appropriate linking is
|
||
|
// done into the corresponding list. On retail builds these map to the regular
|
||
|
// pool allocation wrappers.
|
||
|
//
|
||
|
|
||
|
// Zone allocation to speed up memory management of RxCe entities.
|
||
|
//
|
||
|
|
||
|
ULONG SmbMmRequestZoneEntrySize;
|
||
|
ZONE_HEADER SmbMmRequestZone;
|
||
|
PVOID SmbMmRequestZoneSegmentPtr;
|
||
|
|
||
|
//
|
||
|
// Pool allocation resources and spin locks
|
||
|
//
|
||
|
|
||
|
KSPIN_LOCK SmbMmSpinLock;
|
||
|
|
||
|
ULONG SmbMmExchangeId;
|
||
|
|
||
|
//
|
||
|
// List of the various objects/exchanges allocated.
|
||
|
//
|
||
|
|
||
|
LIST_ENTRY SmbMmExchangesInUse[SENTINEL_EXCHANGE];
|
||
|
LIST_ENTRY SmbMmObjectsInUse[SMBCEDB_OT_SENTINEL];
|
||
|
|
||
|
ULONG ObjectSizeInBytes[SMBCEDB_OT_SENTINEL];
|
||
|
ULONG ExchangeSizeInBytes[SENTINEL_EXCHANGE];
|
||
|
|
||
|
//
|
||
|
// Lookaside lists for Exchange allocation
|
||
|
//
|
||
|
|
||
|
NPAGED_LOOKASIDE_LIST SmbMmExchangesLookasideList[SENTINEL_EXCHANGE];
|
||
|
|
||
|
INLINE PSMBCE_OBJECT_HEADER
|
||
|
SmbMmAllocateObjectPool(
|
||
|
SMBCEDB_OBJECT_TYPE ObjectType,
|
||
|
ULONG PoolType,
|
||
|
ULONG PoolSize)
|
||
|
{
|
||
|
KIRQL SavedIrql;
|
||
|
PVOID pv = NULL;
|
||
|
UCHAR Flags = 0;
|
||
|
|
||
|
PSMBCE_OBJECT_HEADER pHeader = NULL;
|
||
|
|
||
|
ASSERT((ObjectType >= 0) && (ObjectType < SMBCEDB_OT_SENTINEL));
|
||
|
|
||
|
if (ObjectType == SMBCEDB_OT_REQUEST) {
|
||
|
// Acquire the resource lock.
|
||
|
KeAcquireSpinLock( &SmbMmSpinLock, &SavedIrql );
|
||
|
|
||
|
if (!ExIsFullZone( &SmbMmRequestZone )) {
|
||
|
pv = ExAllocateFromZone( &SmbMmRequestZone );
|
||
|
Flags = SMBMM_ZONE_ALLOCATION;
|
||
|
}
|
||
|
|
||
|
// Release the resource lock.
|
||
|
KeReleaseSpinLock( &SmbMmSpinLock, SavedIrql );
|
||
|
}
|
||
|
|
||
|
if (pv == NULL) {
|
||
|
PLIST_ENTRY pListEntry;
|
||
|
|
||
|
pv = RxAllocatePoolWithTag(
|
||
|
PoolType,
|
||
|
PoolSize + sizeof(LIST_ENTRY),
|
||
|
MRXSMB_MM_POOLTAG);
|
||
|
|
||
|
if (pv != NULL) {
|
||
|
pListEntry = (PLIST_ENTRY)pv;
|
||
|
pHeader = (PSMBCE_OBJECT_HEADER)(pListEntry + 1);
|
||
|
|
||
|
ExInterlockedInsertTailList(
|
||
|
&SmbMmObjectsInUse[ObjectType],
|
||
|
pListEntry,
|
||
|
&SmbMmSpinLock);
|
||
|
}
|
||
|
} else {
|
||
|
pHeader = (PSMBCE_OBJECT_HEADER)pv;
|
||
|
}
|
||
|
|
||
|
if (pHeader != NULL) {
|
||
|
// Zero the memory.
|
||
|
RtlZeroMemory( pHeader, PoolSize);
|
||
|
|
||
|
pHeader->Flags = Flags;
|
||
|
}
|
||
|
|
||
|
return pHeader;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
SmbMmFreeObjectPool(
|
||
|
PSMBCE_OBJECT_HEADER pHeader)
|
||
|
{
|
||
|
KIRQL SavedIrql;
|
||
|
BOOLEAN ZoneAllocation = FALSE;
|
||
|
PLIST_ENTRY pListEntry;
|
||
|
|
||
|
ASSERT((pHeader->ObjectType >= 0) && (pHeader->ObjectType < SMBCEDB_OT_SENTINEL));
|
||
|
|
||
|
// Acquire the resource lock.
|
||
|
KeAcquireSpinLock( &SmbMmSpinLock, &SavedIrql );
|
||
|
|
||
|
// Check if it was a zone allocation
|
||
|
if (pHeader->Flags & SMBMM_ZONE_ALLOCATION) {
|
||
|
ZoneAllocation = TRUE;
|
||
|
ExFreeToZone(&SmbMmRequestZone,pHeader);
|
||
|
} else {
|
||
|
pListEntry = (PLIST_ENTRY)((PCHAR)pHeader - sizeof(LIST_ENTRY));
|
||
|
RemoveEntryList(pListEntry);
|
||
|
}
|
||
|
|
||
|
// Release the resource lock.
|
||
|
KeReleaseSpinLock( &SmbMmSpinLock, SavedIrql );
|
||
|
|
||
|
if (!ZoneAllocation) {
|
||
|
RxFreePool(pListEntry);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Construction and destruction of various SMB connection engine objects
|
||
|
//
|
||
|
|
||
|
#define SmbMmInitializeServerEntry(pServerEntry) \
|
||
|
InitializeListHead(&(pServerEntry)->OutstandingRequests.ListHead); \
|
||
|
InitializeListHead(&(pServerEntry)->MidAssignmentRequests.ListHead); \
|
||
|
InitializeListHead(&(pServerEntry)->SecuritySignatureSyncRequests.ListHead); \
|
||
|
InitializeListHead(&(pServerEntry)->Sessions.ListHead); \
|
||
|
InitializeListHead(&(pServerEntry)->NetRoots.ListHead); \
|
||
|
InitializeListHead(&(pServerEntry)->VNetRootContexts.ListHead); \
|
||
|
InitializeListHead(&(pServerEntry)->ActiveExchanges); \
|
||
|
InitializeListHead(&(pServerEntry)->ExpiredExchanges); \
|
||
|
InitializeListHead(&(pServerEntry)->Sessions.DefaultSessionList); \
|
||
|
(pServerEntry)->pTransport = NULL; \
|
||
|
(pServerEntry)->pMidAtlas = NULL
|
||
|
|
||
|
#define SmbMmInitializeSessionEntry(pSessionEntry) \
|
||
|
InitializeListHead(&(pSessionEntry)->Requests.ListHead); \
|
||
|
InitializeListHead(&(pSessionEntry)->SerializationList); \
|
||
|
(pSessionEntry)->DefaultSessionLink.Flink = NULL; \
|
||
|
(pSessionEntry)->DefaultSessionLink.Blink = NULL
|
||
|
|
||
|
#define SmbMmInitializeNetRootEntry(pNetRootEntry) \
|
||
|
InitializeListHead(&(pNetRootEntry)->Requests.ListHead)
|
||
|
|
||
|
#define SmbMmUninitializeServerEntry(pServerEntry) \
|
||
|
ASSERT(IsListEmpty(&(pServerEntry)->OutstandingRequests.ListHead) && \
|
||
|
IsListEmpty(&(pServerEntry)->MidAssignmentRequests.ListHead) && \
|
||
|
IsListEmpty(&(pServerEntry)->SecuritySignatureSyncRequests.ListHead) && \
|
||
|
IsListEmpty(&(pServerEntry)->Sessions.ListHead) && \
|
||
|
IsListEmpty(&(pServerEntry)->NetRoots.ListHead) && \
|
||
|
((pServerEntry)->pMidAtlas == NULL))
|
||
|
|
||
|
#define SmbMmUninitializeSessionEntry(pSessionEntry) \
|
||
|
ASSERT(IsListEmpty(&(pSessionEntry)->Requests.ListHead) && \
|
||
|
((pSessionEntry)->DefaultSessionLink.Flink == NULL))
|
||
|
|
||
|
#define SmbMmUninitializeNetRootEntry(pNetRootEntry) \
|
||
|
ASSERT(IsListEmpty(&(pNetRootEntry)->Requests.ListHead))
|
||
|
|
||
|
#define SmbMmInitializeRequestEntry(pRequestEntry)
|
||
|
|
||
|
#define SmbMmUninitializeRequestEntry(pRequestEntry)
|
||
|
|
||
|
PVOID
|
||
|
SmbMmAllocateObject(
|
||
|
SMBCEDB_OBJECT_TYPE ObjectType)
|
||
|
{
|
||
|
PSMBCE_OBJECT_HEADER pHeader;
|
||
|
|
||
|
ASSERT((ObjectType >= 0) && (ObjectType < SMBCEDB_OT_SENTINEL));
|
||
|
|
||
|
pHeader = SmbMmAllocateObjectPool(
|
||
|
ObjectType,
|
||
|
NonPagedPool,
|
||
|
ObjectSizeInBytes[ObjectType]);
|
||
|
|
||
|
if (pHeader != NULL) {
|
||
|
pHeader->NodeType = SMB_CONNECTION_ENGINE_NTC(ObjectType);
|
||
|
pHeader->State = SMBCEDB_START_CONSTRUCTION;
|
||
|
|
||
|
switch (ObjectType) {
|
||
|
case SMBCEDB_OT_SERVER :
|
||
|
SmbMmInitializeServerEntry((PSMBCEDB_SERVER_ENTRY)pHeader);
|
||
|
break;
|
||
|
|
||
|
case SMBCEDB_OT_NETROOT :
|
||
|
SmbMmInitializeNetRootEntry((PSMBCEDB_NET_ROOT_ENTRY)pHeader);
|
||
|
break;
|
||
|
|
||
|
case SMBCEDB_OT_REQUEST :
|
||
|
SmbMmInitializeRequestEntry((PSMBCEDB_REQUEST_ENTRY)pHeader);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ASSERT(!"Valid Type for SmbMmAllocateObject");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pHeader;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
SmbMmFreeObject(
|
||
|
PVOID pv)
|
||
|
{
|
||
|
PSMBCE_OBJECT_HEADER pHeader = (PSMBCE_OBJECT_HEADER)pv;
|
||
|
|
||
|
switch (pHeader->ObjectType) {
|
||
|
case SMBCEDB_OT_SERVER :
|
||
|
SmbMmUninitializeServerEntry((PSMBCEDB_SERVER_ENTRY)pHeader);
|
||
|
break;
|
||
|
|
||
|
case SMBCEDB_OT_NETROOT :
|
||
|
SmbMmUninitializeNetRootEntry((PSMBCEDB_NET_ROOT_ENTRY)pHeader);
|
||
|
break;
|
||
|
|
||
|
case SMBCEDB_OT_REQUEST :
|
||
|
SmbMmUninitializeRequestEntry((PSMBCEDB_REQUEST_ENTRY)pHeader);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ASSERT(!"Valid Type for SmbMmFreeObject");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
SmbMmFreeObjectPool(pHeader);
|
||
|
}
|
||
|
|
||
|
PSMBCEDB_SESSION_ENTRY
|
||
|
SmbMmAllocateSessionEntry(
|
||
|
PSMBCEDB_SERVER_ENTRY pServerEntry,
|
||
|
BOOLEAN RemoteBootSession)
|
||
|
{
|
||
|
PSMBCEDB_SESSION_ENTRY pSessionEntry;
|
||
|
SESSION_TYPE SessionType;
|
||
|
ULONG SessionSize;
|
||
|
|
||
|
PAGED_CODE();
|
||
|
|
||
|
SessionSize = sizeof(SMBCEDB_SESSION_ENTRY) -
|
||
|
sizeof(SMBCE_SESSION);
|
||
|
|
||
|
if (pServerEntry->Header.State != SMBCEDB_INVALID) {
|
||
|
if ((pServerEntry->Server.DialectFlags & DF_EXTENDED_SECURITY) && !RemoteBootSession) {
|
||
|
SessionSize += sizeof(SMBCE_EXTENDED_SESSION);
|
||
|
|
||
|
SessionType = EXTENDED_NT_SESSION;
|
||
|
} else {
|
||
|
// allocate a LANMAN session
|
||
|
SessionSize += sizeof(SMBCE_SESSION);
|
||
|
SessionType = LANMAN_SESSION;
|
||
|
}
|
||
|
} else {
|
||
|
SessionSize += sizeof(SMBCE_EXTENDED_SESSION);
|
||
|
SessionType = UNINITIALIZED_SESSION;
|
||
|
}
|
||
|
|
||
|
pSessionEntry = (PSMBCEDB_SESSION_ENTRY)
|
||
|
SmbMmAllocateObjectPool(
|
||
|
SMBCEDB_OT_SESSION,
|
||
|
NonPagedPool,
|
||
|
SessionSize);
|
||
|
|
||
|
if (pSessionEntry != NULL) {
|
||
|
pSessionEntry->Header.NodeType = SMB_CONNECTION_ENGINE_NTC(SMBCEDB_OT_SESSION);
|
||
|
pSessionEntry->Header.State = SMBCEDB_START_CONSTRUCTION;
|
||
|
pSessionEntry->Session.Type = SessionType;
|
||
|
|
||
|
SmbMmInitializeSessionEntry(pSessionEntry);
|
||
|
|
||
|
SecInvalidateHandle( &pSessionEntry->Session.CredentialHandle );
|
||
|
SecInvalidateHandle( &pSessionEntry->Session.SecurityContextHandle );
|
||
|
|
||
|
if (SessionType == EXTENDED_NT_SESSION) {
|
||
|
PSMBCE_EXTENDED_SESSION pExtSecuritySession = (PSMBCE_EXTENDED_SESSION)&pSessionEntry->Session;
|
||
|
pExtSecuritySession->pServerResponseBlob = NULL;
|
||
|
pExtSecuritySession->ServerResponseBlobLength = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pSessionEntry;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
SmbMmFreeSessionEntry(
|
||
|
PSMBCEDB_SESSION_ENTRY pSessionEntry)
|
||
|
{
|
||
|
PAGED_CODE();
|
||
|
|
||
|
if (pSessionEntry->Session.Type == EXTENDED_NT_SESSION) {
|
||
|
// KERBEROS specific asserts
|
||
|
}
|
||
|
|
||
|
SmbMmUninitializeSessionEntry(pSessionEntry);
|
||
|
|
||
|
SmbMmFreeObjectPool(&pSessionEntry->Header);
|
||
|
}
|
||
|
|
||
|
|
||
|
PVOID
|
||
|
SmbMmAllocateExchange(
|
||
|
SMB_EXCHANGE_TYPE ExchangeType,
|
||
|
PVOID pv)
|
||
|
{
|
||
|
KIRQL SavedIrql;
|
||
|
ULONG SizeInBytes;
|
||
|
USHORT Flags = 0;
|
||
|
PSMB_EXCHANGE pExchange = NULL;
|
||
|
PLIST_ENTRY pListEntry;
|
||
|
|
||
|
ASSERT((ExchangeType >= 0) && (ExchangeType < SENTINEL_EXCHANGE));
|
||
|
|
||
|
if (pv==NULL) {
|
||
|
pv = ExAllocateFromNPagedLookasideList(
|
||
|
&SmbMmExchangesLookasideList[ExchangeType]);
|
||
|
} else {
|
||
|
Flags |= SMBCE_EXCHANGE_NOT_FROM_POOL;
|
||
|
}
|
||
|
|
||
|
if (pv != NULL) {
|
||
|
// Initialize the object header
|
||
|
pExchange = (PSMB_EXCHANGE)(pv);
|
||
|
|
||
|
// Zero the memory.
|
||
|
RtlZeroMemory(
|
||
|
pExchange,
|
||
|
ExchangeSizeInBytes[ExchangeType]);
|
||
|
|
||
|
pExchange->NodeTypeCode = SMB_EXCHANGE_NTC(ExchangeType);
|
||
|
pExchange->NodeByteSize = (USHORT)ExchangeSizeInBytes[ExchangeType];
|
||
|
|
||
|
pExchange->SmbCeState = SMBCE_EXCHANGE_INITIALIZATION_START;
|
||
|
pExchange->SmbCeFlags = Flags;
|
||
|
|
||
|
InitializeListHead(&pExchange->ExchangeList);
|
||
|
InitializeListHead(&pExchange->CancelledList);
|
||
|
|
||
|
switch (pExchange->Type) {
|
||
|
case CONSTRUCT_NETROOT_EXCHANGE:
|
||
|
pExchange->pDispatchVector = &ConstructNetRootExchangeDispatch;
|
||
|
break;
|
||
|
|
||
|
case TRANSACT_EXCHANGE :
|
||
|
pExchange->pDispatchVector = &TransactExchangeDispatch;
|
||
|
break;
|
||
|
|
||
|
case EXTENDED_SESSION_SETUP_EXCHANGE:
|
||
|
pExchange->pDispatchVector = &ExtendedSessionSetupExchangeDispatch;
|
||
|
break;
|
||
|
|
||
|
case ADMIN_EXCHANGE:
|
||
|
pExchange->pDispatchVector = &AdminExchangeDispatch;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Acquire the resource lock.
|
||
|
KeAcquireSpinLock( &SmbMmSpinLock, &SavedIrql );
|
||
|
|
||
|
InsertTailList(
|
||
|
&SmbMmExchangesInUse[pExchange->Type],
|
||
|
&pExchange->SmbMmInUseListEntry);
|
||
|
|
||
|
pExchange->Id = SmbMmExchangeId++;
|
||
|
|
||
|
// Release the resource lock.
|
||
|
KeReleaseSpinLock( &SmbMmSpinLock, SavedIrql );
|
||
|
}
|
||
|
|
||
|
return pExchange;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
SmbMmFreeExchange(
|
||
|
PSMB_EXCHANGE pExchange)
|
||
|
{
|
||
|
if (pExchange != NULL) {
|
||
|
SMB_EXCHANGE_TYPE ExchangeType;
|
||
|
|
||
|
KIRQL SavedIrql;
|
||
|
|
||
|
ExchangeType = pExchange->Type;
|
||
|
|
||
|
ASSERT((ExchangeType >= 0) && (ExchangeType < SENTINEL_EXCHANGE));
|
||
|
ASSERT(pExchange->MdlForServerResponse == NULL &&
|
||
|
pExchange->BufferForServerResponse == NULL);
|
||
|
|
||
|
if (pExchange->WorkQueueItem.List.Flink != NULL) {
|
||
|
//DbgBreakPoint();
|
||
|
}
|
||
|
|
||
|
// Acquire the resource lock.
|
||
|
KeAcquireSpinLock( &SmbMmSpinLock, &SavedIrql );
|
||
|
|
||
|
RemoveEntryList(&pExchange->SmbMmInUseListEntry);
|
||
|
|
||
|
// Release the resource lock.
|
||
|
KeReleaseSpinLock( &SmbMmSpinLock, SavedIrql );
|
||
|
|
||
|
if (!FlagOn(pExchange->SmbCeFlags,SMBCE_EXCHANGE_NOT_FROM_POOL)) {
|
||
|
ExFreeToNPagedLookasideList(
|
||
|
&SmbMmExchangesLookasideList[ExchangeType],
|
||
|
pExchange);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PVOID
|
||
|
SmbMmAllocateServerTransport(
|
||
|
SMBCE_SERVER_TRANSPORT_TYPE ServerTransportType)
|
||
|
{
|
||
|
PSMBCE_OBJECT_HEADER pHeader;
|
||
|
|
||
|
ULONG AllocationSize;
|
||
|
ULONG PoolTag;
|
||
|
|
||
|
PAGED_CODE();
|
||
|
|
||
|
switch (ServerTransportType) {
|
||
|
case SMBCE_STT_VC:
|
||
|
AllocationSize = sizeof(SMBCE_SERVER_VC_TRANSPORT);
|
||
|
PoolTag = MRXSMB_VC_POOLTAG;
|
||
|
break;
|
||
|
|
||
|
case SMBCE_STT_MAILSLOT:
|
||
|
AllocationSize = sizeof(SMBCE_SERVER_MAILSLOT_TRANSPORT);
|
||
|
PoolTag = MRXSMB_MAILSLOT_POOLTAG;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ASSERT(!"Valid Server Transport Type");
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
pHeader = (PSMBCE_OBJECT_HEADER)
|
||
|
RxAllocatePoolWithTag(
|
||
|
NonPagedPool,
|
||
|
AllocationSize,
|
||
|
PoolTag);
|
||
|
|
||
|
if (pHeader != NULL) {
|
||
|
PSMBCE_SERVER_TRANSPORT pServerTransport;
|
||
|
|
||
|
RtlZeroMemory(pHeader,AllocationSize);
|
||
|
|
||
|
pHeader->ObjectCategory = SMB_SERVER_TRANSPORT_CATEGORY;
|
||
|
pHeader->ObjectType = (UCHAR)ServerTransportType;
|
||
|
pHeader->SwizzleCount = 0;
|
||
|
pHeader->State = 0;
|
||
|
pHeader->Flags = 0;
|
||
|
|
||
|
pServerTransport = (PSMBCE_SERVER_TRANSPORT)pHeader;
|
||
|
|
||
|
pServerTransport->pRundownEvent = NULL;
|
||
|
|
||
|
switch (ServerTransportType) {
|
||
|
case SMBCE_STT_MAILSLOT:
|
||
|
break;
|
||
|
|
||
|
case SMBCE_STT_VC:
|
||
|
{
|
||
|
PSMBCE_SERVER_VC_TRANSPORT pVcTransport;
|
||
|
|
||
|
pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pHeader;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pHeader;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
SmbMmFreeServerTransport(
|
||
|
PSMBCE_SERVER_TRANSPORT pServerTransport)
|
||
|
{
|
||
|
PAGED_CODE();
|
||
|
|
||
|
ASSERT((pServerTransport->SwizzleCount == 0) &&
|
||
|
(pServerTransport->ObjectCategory == SMB_SERVER_TRANSPORT_CATEGORY));
|
||
|
|
||
|
RxFreePool(pServerTransport);
|
||
|
}
|
||
|
|
||
|
NTSTATUS SmbMmInit()
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine initialises the connection engine structures for memory management
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
STATUS_SUCCESS if successful, otherwise an informative error code.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
ULONG ZoneSegmentSize;
|
||
|
|
||
|
PAGED_CODE();
|
||
|
|
||
|
// Initialize the resource lock for the zone allocator.
|
||
|
KeInitializeSpinLock( &SmbMmSpinLock );
|
||
|
|
||
|
SmbMmRequestZoneEntrySize = QuadAlign(sizeof(SMBCEDB_REQUEST_ENTRY));
|
||
|
|
||
|
// Currently the request zone size is restricted to that of a page. This can and should
|
||
|
// be fine tuned.
|
||
|
ZoneSegmentSize = PAGE_SIZE;
|
||
|
|
||
|
SmbMmRequestZoneSegmentPtr = RxAllocatePoolWithTag(
|
||
|
NonPagedPool,
|
||
|
ZoneSegmentSize,
|
||
|
MRXSMB_MM_POOLTAG);
|
||
|
|
||
|
if (SmbMmRequestZoneSegmentPtr != NULL) {
|
||
|
SMB_EXCHANGE_TYPE ExchangeType;
|
||
|
|
||
|
ExInitializeZone(
|
||
|
&SmbMmRequestZone,
|
||
|
SmbMmRequestZoneEntrySize,
|
||
|
SmbMmRequestZoneSegmentPtr,
|
||
|
ZoneSegmentSize );
|
||
|
|
||
|
// set up the sizes for allocation.
|
||
|
ObjectSizeInBytes[SMBCEDB_OT_SERVER] = sizeof(SMBCEDB_SERVER_ENTRY);
|
||
|
ObjectSizeInBytes[SMBCEDB_OT_NETROOT] = sizeof(SMBCEDB_NET_ROOT_ENTRY);
|
||
|
ObjectSizeInBytes[SMBCEDB_OT_SESSION] = sizeof(SMBCEDB_SESSION_ENTRY);
|
||
|
ObjectSizeInBytes[SMBCEDB_OT_REQUEST] = sizeof(SMBCEDB_REQUEST_ENTRY);
|
||
|
|
||
|
ExchangeSizeInBytes[CONSTRUCT_NETROOT_EXCHANGE] = sizeof(SMB_CONSTRUCT_NETROOT_EXCHANGE);
|
||
|
ExchangeSizeInBytes[TRANSACT_EXCHANGE] = sizeof(SMB_TRANSACT_EXCHANGE);
|
||
|
ExchangeSizeInBytes[ORDINARY_EXCHANGE] = sizeof(SMB_PSE_ORDINARY_EXCHANGE);
|
||
|
ExchangeSizeInBytes[EXTENDED_SESSION_SETUP_EXCHANGE]
|
||
|
= sizeof(SMB_EXTENDED_SESSION_SETUP_EXCHANGE);
|
||
|
ExchangeSizeInBytes[ADMIN_EXCHANGE] = sizeof(SMB_ADMIN_EXCHANGE);
|
||
|
|
||
|
InitializeListHead(&SmbMmExchangesInUse[CONSTRUCT_NETROOT_EXCHANGE]);
|
||
|
ExInitializeNPagedLookasideList(
|
||
|
&SmbMmExchangesLookasideList[CONSTRUCT_NETROOT_EXCHANGE],
|
||
|
ExAllocatePoolWithTag,
|
||
|
ExFreePool,
|
||
|
0,
|
||
|
sizeof(SMB_CONSTRUCT_NETROOT_EXCHANGE),
|
||
|
MRXSMB_MM_POOLTAG,
|
||
|
1);
|
||
|
|
||
|
InitializeListHead(&SmbMmExchangesInUse[TRANSACT_EXCHANGE]);
|
||
|
ExInitializeNPagedLookasideList(
|
||
|
&SmbMmExchangesLookasideList[TRANSACT_EXCHANGE],
|
||
|
ExAllocatePoolWithTag,
|
||
|
ExFreePool,
|
||
|
0,
|
||
|
sizeof(SMB_TRANSACT_EXCHANGE),
|
||
|
MRXSMB_MM_POOLTAG,
|
||
|
2);
|
||
|
|
||
|
InitializeListHead(&SmbMmExchangesInUse[ORDINARY_EXCHANGE]);
|
||
|
ExInitializeNPagedLookasideList(
|
||
|
&SmbMmExchangesLookasideList[ORDINARY_EXCHANGE],
|
||
|
ExAllocatePoolWithTag,
|
||
|
ExFreePool,
|
||
|
0,
|
||
|
sizeof(SMB_PSE_ORDINARY_EXCHANGE),
|
||
|
MRXSMB_MM_POOLTAG,
|
||
|
4);
|
||
|
|
||
|
InitializeListHead(&SmbMmExchangesInUse[EXTENDED_SESSION_SETUP_EXCHANGE]);
|
||
|
ExInitializeNPagedLookasideList(
|
||
|
&SmbMmExchangesLookasideList[EXTENDED_SESSION_SETUP_EXCHANGE],
|
||
|
ExAllocatePoolWithTag,
|
||
|
ExFreePool,
|
||
|
0,
|
||
|
sizeof(SMB_EXTENDED_SESSION_SETUP_EXCHANGE),
|
||
|
MRXSMB_MM_POOLTAG,
|
||
|
1);
|
||
|
|
||
|
InitializeListHead(&SmbMmExchangesInUse[ADMIN_EXCHANGE]);
|
||
|
ExInitializeNPagedLookasideList(
|
||
|
&SmbMmExchangesLookasideList[ADMIN_EXCHANGE],
|
||
|
ExAllocatePoolWithTag,
|
||
|
ExFreePool,
|
||
|
0,
|
||
|
sizeof(SMB_ADMIN_EXCHANGE),
|
||
|
MRXSMB_MM_POOLTAG,
|
||
|
1);
|
||
|
|
||
|
InitializeListHead(&SmbMmObjectsInUse[SMBCEDB_OT_SERVER]);
|
||
|
InitializeListHead(&SmbMmObjectsInUse[SMBCEDB_OT_SESSION]);
|
||
|
InitializeListHead(&SmbMmObjectsInUse[SMBCEDB_OT_NETROOT]);
|
||
|
InitializeListHead(&SmbMmObjectsInUse[SMBCEDB_OT_REQUEST]);
|
||
|
|
||
|
SmbMmExchangeId = 1;
|
||
|
} else {
|
||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
VOID SmbMmTearDown()
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine tears down the memory management structures in the SMB connection
|
||
|
engine
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
PAGED_CODE();
|
||
|
|
||
|
// free the segment associated with RxCe object allocation.
|
||
|
RxFreePool(SmbMmRequestZoneSegmentPtr);
|
||
|
|
||
|
ExDeleteNPagedLookasideList(
|
||
|
&SmbMmExchangesLookasideList[CONSTRUCT_NETROOT_EXCHANGE]);
|
||
|
|
||
|
ExDeleteNPagedLookasideList(
|
||
|
&SmbMmExchangesLookasideList[TRANSACT_EXCHANGE]);
|
||
|
|
||
|
ExDeleteNPagedLookasideList(
|
||
|
&SmbMmExchangesLookasideList[ORDINARY_EXCHANGE]);
|
||
|
|
||
|
ExDeleteNPagedLookasideList(
|
||
|
&SmbMmExchangesLookasideList[EXTENDED_SESSION_SETUP_EXCHANGE]);
|
||
|
|
||
|
ExDeleteNPagedLookasideList(
|
||
|
&SmbMmExchangesLookasideList[ADMIN_EXCHANGE]);
|
||
|
}
|
||
|
|
||
|
|
||
|
|