NT4/private/ntos/srv/svcsrv.c
2020-09-30 17:12:29 +02:00

580 lines
16 KiB
C
Raw Blame History

This file contains invisible Unicode characters

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

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
svcsrv.c
Abstract:
This module contains routines for supporting the server APIs in the
server service, SrvNetServerDiskEnum, and SrvNetServerSetInfo.
Author:
David Treadwell (davidtr) 31-Jan-1991
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//
// Forward declarations.
//
LARGE_INTEGER
SecondsToTime (
IN ULONG Seconds,
IN BOOLEAN MakeNegative
);
LARGE_INTEGER
MinutesToTime (
IN ULONG Seconds,
IN BOOLEAN MakeNegative
);
ULONG
MultipleOfProcessors (
IN ULONG value
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, SrvNetServerDiskEnum )
#pragma alloc_text( PAGE, SrvNetServerSetInfo )
#pragma alloc_text( PAGE, SecondsToTime )
#pragma alloc_text( PAGE, MinutesToTime )
#pragma alloc_text( PAGE, MultipleOfProcessors )
#endif
NTSTATUS
SrvNetServerDiskEnum (
IN PSERVER_REQUEST_PACKET Srp,
IN PVOID Buffer,
IN ULONG BufferLength
)
{
PAGED_CODE( );
Srp, Buffer, BufferLength;
return STATUS_NOT_IMPLEMENTED;
} // SrvNetServerDiskEnum
NTSTATUS
SrvNetServerSetInfo (
IN PSERVER_REQUEST_PACKET Srp,
IN PVOID Buffer,
IN ULONG BufferLength
)
/*++
Routine Description:
This routine processes the NetServerSetInfo API in the server FSD.
Arguments:
Srp - a pointer to the server request packet that contains all
the information necessary to satisfy the request. This includes:
INPUT:
None.
OUTPUT:
None.
Buffer - a pointer to a SERVER_INFO_102, followed immediately by a
SERVER_INFO_599 structure, followed by a SERVER_INFO_559a
structure. All information is always reset in this routine; the
server service also tracks this data, so when it gets a
NetServerSetInfo it overwrites the appropriate fields and sends
all the data.
BufferLength - total length of this buffer.
Return Value:
NTSTATUS - result of operation to return to the server service.
--*/
{
NTSTATUS status;
BOOLEAN fullStructSpecified;
PSERVER_INFO_102 sv102;
PSERVER_INFO_599 sv599;
PSERVER_INFO_598 sv598;
LARGE_INTEGER scavengerTimeout;
LARGE_INTEGER alerterTimeout;
ULONG ipxdisc;
LARGE_INTEGER li;
ULONG bufferOffset;
ULONG keTimeIncrement;
PAGED_CODE( );
BufferLength;
//
// Make sure that the input buffer length is correct.
//
if ( BufferLength == sizeof(SERVER_INFO_102) + sizeof(SERVER_INFO_599) ) {
fullStructSpecified = FALSE;
} else if ( BufferLength == sizeof(SERVER_INFO_102) +
sizeof(SERVER_INFO_599) + sizeof(SERVER_INFO_598) ) {
fullStructSpecified = TRUE;
} else {
return STATUS_INVALID_PARAMETER;
}
//
// Set up buffer pointers as appropriate. The SERVER_INFO_599
// structure must immediately follow the SERVER_INFO_102 structure
// in the buffer.
//
sv102 = Buffer;
sv599 = (PSERVER_INFO_599)(sv102 + 1);
sv598 = (PSERVER_INFO_598)(sv599 + 1);
//
// store the time increment count
//
keTimeIncrement = KeQueryTimeIncrement();
//
// Grab the lock that protects configuration changes.
//
ACQUIRE_LOCK( &SrvConfigurationLock );
//
// Set all configuration information in the server.
//
SrvMaxUsers = sv102->sv102_users;
//
// The autodisconnect timeout must be converted from minutes to NT
// time, which has a base of 100s of nanoseconds. If the specified
// value is negative (top bit set), set the timeout to 0, indicating
// that no autodisconnect should be done. If the specified value is
// 0, meaning to autodisconnect immediately, set the timeout to a
// small value, but not 0.
//
if ( (sv102->sv102_disc & 0x80000000) == 0 ) {
if ( sv102->sv102_disc != 0 ) {
SrvAutodisconnectTimeout.QuadPart =
Int32x32To64( sv102->sv102_disc, 10*1000*1000*60 );
} else {
SrvAutodisconnectTimeout.QuadPart = 1;
}
} else {
SrvAutodisconnectTimeout.QuadPart = 0;
}
SrvInitialSessionTableSize = (CSHORT)sv599->sv599_initsesstable;
SrvInitialTreeTableSize = (CSHORT)sv599->sv599_initconntable;
SrvInitialFileTableSize = (CSHORT)sv599->sv599_initfiletable;
SrvInitialSearchTableSize = (CSHORT)sv599->sv599_initsearchtable;
SrvMaxFileTableSize = (CSHORT)sv599->sv599_sessopens;
SrvMaxNumberVcs = sv599->sv599_sessvcs;
SrvMaxSearchTableSize = (CSHORT)sv599->sv599_opensearch;
SrvReceiveBufferLength = sv599->sv599_sizreqbuf;
SrvReceiveBufferSize = (SrvReceiveBufferLength + SrvCacheLineSize) & ~SrvCacheLineSize;
SrvReceiveMdlSize = (MmSizeOfMdl( (PVOID)(PAGE_SIZE-1), SrvReceiveBufferSize ) + 7) & ~7;
SrvMaxMdlSize = (MmSizeOfMdl( (PVOID)(PAGE_SIZE-1), MAX_PARTIAL_BUFFER_SIZE ) + 7) & ~7;
SrvInitialReceiveWorkItemCount = sv599->sv599_initworkitems;
SrvMaxReceiveWorkItemCount = sv599->sv599_maxworkitems;
SrvInitialRawModeWorkItemCount = sv599->sv599_rawworkitems;
SrvReceiveIrpStackSize = (CCHAR)sv599->sv599_irpstacksize;
SrvReceiveIrpSize = (IoSizeOfIrp( SrvReceiveIrpStackSize ) + 7) & ~7;
SrvMaxSessionTableSize = (CSHORT)sv599->sv599_sessusers;
SrvMaxTreeTableSize = (CSHORT)sv599->sv599_sessconns;
SrvMaxPagedPoolUsage = sv599->sv599_maxpagedmemoryusage;
SrvMaxNonPagedPoolUsage = sv599->sv599_maxnonpagedmemoryusage;
SrvEnableSoftCompatibility = (BOOLEAN)sv599->sv599_enablesoftcompat;
SrvEnableForcedLogoff = (BOOLEAN)sv599->sv599_enableforcedlogoff;
SrvCoreSearchTimeout = sv599->sv599_maxkeepsearch;
SrvSearchMaxTimeout = SecondsToTime( SrvCoreSearchTimeout, FALSE );
SrvScavengerTimeoutInSeconds = sv599->sv599_scavtimeout;
scavengerTimeout = SecondsToTime( SrvScavengerTimeoutInSeconds, FALSE );
SrvMaxMpxCount = (CSHORT)sv599->sv599_maxmpxct;
SrvWaitForOplockBreakTime = SecondsToTime( sv599->sv599_oplockbreakwait, FALSE );
SrvWaitForOplockBreakRequestTime = SecondsToTime( sv599->sv599_oplockbreakresponsewait, FALSE );
SrvMinReceiveQueueLength = sv599->sv599_minrcvqueue;
SrvMinFreeWorkItemsBlockingIo = sv599->sv599_minfreeworkitems;
SrvXsSectionSize.QuadPart = sv599->sv599_xactmemsize;
SrvThreadPriority = (KPRIORITY)sv599->sv599_threadpriority;
SrvEnableOplockForceClose = (BOOLEAN)sv599->sv599_enableoplockforceclose;
SrvEnableFcbOpens = (BOOLEAN)sv599->sv599_enablefcbopens;
SrvEnableRawMode = (BOOLEAN)sv599->sv599_enableraw;
SrvFreeConnectionMinimum = sv599->sv599_minfreeconnections;
SrvFreeConnectionMaximum = sv599->sv599_maxfreeconnections;
//
// Max work item idle time is in ticks
//
li = SecondsToTime( sv599->sv599_maxworkitemidletime, FALSE );
li.QuadPart /= keTimeIncrement;
if ( li.HighPart != 0 ) {
li.LowPart = 0xffffffff;
}
SrvWorkItemMaxIdleTime = li.LowPart;
//
// Oplocks should not be enabled if SrvMaxMpxCount == 1
//
if ( SrvMaxMpxCount > 1 ) {
SrvEnableOplocks = (BOOLEAN)sv599->sv599_enableoplocks;
} else {
SrvEnableOplocks = FALSE;
}
SrvProductTypeServer = MmIsThisAnNtAsSystem( );
if ( fullStructSpecified ) {
SrvServerSize = sv598->sv598_serversize;
SrvMaxRawModeWorkItemCount = sv598->sv598_maxrawworkitems;
SrvMaxThreadsPerQueue = sv598->sv598_maxthreadsperqueue;
ipxdisc = sv598->sv598_connectionlessautodisc;
SrvRemoveDuplicateSearches =
(BOOLEAN)sv598->sv598_removeduplicatesearches;
SrvMaxOpenSearches = sv598->sv598_maxglobalopensearch;
SrvSharingViolationRetryCount = sv598->sv598_sharingviolationretries;
SrvSharingViolationDelay.QuadPart =
Int32x32To64( sv598->sv598_sharingviolationdelay, -1*10*1000 );
SrvLockViolationDelay = sv598->sv598_lockviolationdelay;
SrvLockViolationOffset = sv598->sv598_lockviolationoffset;
SrvCachedOpenLimit = sv598->sv598_cachedopenlimit;
SrvMdlReadSwitchover = sv598->sv598_mdlreadswitchover;
SrvEnableWfW311DirectIpx =
(BOOLEAN)sv598->sv598_enablewfw311directipx;
SrvRestrictNullSessionAccess =
(BOOLEAN)sv598->sv598_restrictnullsessaccess;
SrvQueueCalc = SecondsToTime( sv598->sv598_queuesamplesecs, FALSE );
SrvPreferredAffinity = sv598->sv598_preferredaffinity;
SrvOtherQueueAffinity = sv598->sv598_otherqueueaffinity;
SrvBalanceCount = sv598->sv598_balancecount;
SrvMaxFreeRfcbs = sv598->sv598_maxfreerfcbs;
SrvMaxFreeMfcbs = sv598->sv598_maxfreemfcbs;
SrvMaxPagedPoolChunkSize = sv598->sv598_maxpagedpoolchunksize;
SrvMaxCachedDirectory = sv598->sv598_cacheddirectorylimit;
SrvMaxCopyLength = sv598->sv598_maxcopylength;
//
// See if a Kerberos realm is given
//
if(Srp->Name1.Length
&&
Srp->Name1.Buffer[0] == L'\\')
{
//
// it appears to be a Kerberos realm. So let's
// take it
//
KerberosRealm.Buffer = ExAllocatePool(PagedPool,
Srp->Name1.MaximumLength);
if(KerberosRealm.Buffer)
{
KerberosRealm.Length = Srp->Name1.Length;
KerberosRealm.MaximumLength = Srp->Name1.MaximumLength;
RtlMoveMemory(KerberosRealm.Buffer,
Srp->Name1.Buffer,
KerberosRealm.MaximumLength);
}
}
SrvSupportsBulkTransfer = sv598->sv598_enablebulktransfer;
SrvSupportsCompression = sv598->sv598_enablecompression;
} else {
SrvServerSize = 0;
SrvMaxRawModeWorkItemCount = SrvInitialRawModeWorkItemCount;
SrvMaxThreadsPerQueue = 25;
ipxdisc = 0;
SrvRemoveDuplicateSearches = TRUE;
SrvMaxOpenSearches = 4096;
SrvSharingViolationRetryCount = 5;
SrvSharingViolationDelay.QuadPart = -200 * 10 * 1000; // 200 ms
SrvLockViolationDelay = 250;
SrvLockViolationOffset = 0xef000000;
SrvCachedOpenLimit = 0;
SrvEnableWfW311DirectIpx = TRUE;
SrvRestrictNullSessionAccess = TRUE;
SrvMaxFreeRfcbs = 5;
SrvMaxFreeMfcbs = 5;
SrvMaxPagedPoolChunkSize = 512;
SrvMaxCachedDirectory = 5;
//
// Mdl switchover length should not exceed the receive buffer length.
//
SrvMdlReadSwitchover = MIN(SrvReceiveBufferLength, 1024);
}
SrvMaxNonPagedPoolChunkSize = 512;
SrvMaxPagedPoolChunkSize = 512;
SrvLockViolationDelayRelative.QuadPart =
Int32x32To64( sv598->sv598_lockviolationdelay, -1*10*1000 );
//
// Calculate switchover number for mpx
//
bufferOffset = (sizeof(SMB_HEADER) + sizeof(RESP_READ_MPX) - 1 + 3) & ~3;
if ( SrvMdlReadSwitchover > (SrvReceiveBufferLength - bufferOffset) ) {
SrvMpxMdlReadSwitchover = SrvReceiveBufferLength - bufferOffset;
} else {
SrvMpxMdlReadSwitchover = SrvMdlReadSwitchover;
}
//
// The IPX autodisconnect timeout must be converted from minutes to
// ticks. If 0 is specified, use 15 minutes.
//
if ( ipxdisc == 0 ) {
ipxdisc = 15;
}
li.QuadPart = Int32x32To64( ipxdisc, 10*1000*1000*60 );
li.QuadPart /= keTimeIncrement;
if ( li.HighPart != 0 ) {
li.LowPart = 0xffffffff;
}
SrvIpxAutodisconnectTimeout = li.LowPart;
//
// Event logging and alerting information.
//
alerterTimeout = MinutesToTime( sv599->sv599_alertschedule, FALSE );
SrvAlertMinutes = sv599->sv599_alertschedule;
SrvErrorRecord.ErrorThreshold = sv599->sv599_errorthreshold;
SrvNetworkErrorRecord.ErrorThreshold =
sv599->sv599_networkerrorthreshold;
SrvFreeDiskSpaceThreshold = sv599->sv599_diskspacethreshold;
SrvCaptureScavengerTimeout( &scavengerTimeout, &alerterTimeout );
//
// Link Speed Parameters
//
SrvMaxLinkDelay = SecondsToTime( sv599->sv599_maxlinkdelay, FALSE );
SrvMinLinkThroughput.QuadPart = sv599->sv599_minlinkthroughput;
SrvLinkInfoValidTime =
SecondsToTime ( sv599->sv599_linkinfovalidtime, FALSE );
SrvScavengerUpdateQosCount =
sv599->sv599_scavqosinfoupdatetime / sv599->sv599_scavtimeout;
//
// Override parameters that cannot be set on WinNT (vs. NTAS).
//
// We override the parameters passed by the service in case somebody
// figures out the FSCTL that changes parameters. We also override
// in the service in order to keep the service's view consistent
// with the server's. If you make any changes here, also make them
// in srvsvc\server\registry.c.
//
if ( !SrvProductTypeServer ) {
//
// On WinNT, the maximum value of certain parameters is fixed at
// build time. These include: concurrent users, SMB buffers,
//
#define MINIMIZE(_param,_max) _param = MIN( _param, _max );
MINIMIZE( SrvMaxUsers, MAX_USERS_WKSTA );
MINIMIZE( SrvMaxReceiveWorkItemCount, MAX_MAXWORKITEMS_WKSTA );
MINIMIZE( SrvMaxThreadsPerQueue, MAX_THREADS_WKSTA );
//
// On WinNT, we do not cache the following:
//
SrvCachedOpenLimit = 0; // don't cache close'd files
SrvMaxCachedDirectory = 0; // don't cache directory names
SrvMaxFreeRfcbs = 0; // don't cache free'd RFCB structs
SrvMaxFreeMfcbs = 0; // don't cache free'd NONPAGED_MFCB structs
}
//
// The following items are generally per-processor. Ensure they
// are a multiple of the number of processors in the system.
//
SrvMaxReceiveWorkItemCount =
MultipleOfProcessors( SrvMaxReceiveWorkItemCount );
SrvInitialReceiveWorkItemCount =
MultipleOfProcessors( SrvInitialReceiveWorkItemCount );
SrvMinReceiveQueueLength =
MultipleOfProcessors( SrvMinReceiveQueueLength );
SrvMaxRawModeWorkItemCount =
MultipleOfProcessors( SrvMaxRawModeWorkItemCount );
SrvInitialRawModeWorkItemCount =
MultipleOfProcessors( SrvInitialRawModeWorkItemCount );
RELEASE_LOCK( &SrvConfigurationLock );
return STATUS_SUCCESS;
} // SrvNetServerSetInfo
LARGE_INTEGER
SecondsToTime (
IN ULONG Seconds,
IN BOOLEAN MakeNegative
)
/*++
Routine Description:
This routine converts a time interval specified in seconds to
the NT time base in 100s on nanoseconds.
Arguments:
Seconds - the interval in seconds.
MakeNegative - if TRUE, the time returned is a negative, i.e. relative
time.
Return Value:
LARGE_INTEGER - the interval in NT time.
--*/
{
LARGE_INTEGER ntTime;
PAGED_CODE( );
if ( MakeNegative ) {
ntTime.QuadPart = Int32x32To64( Seconds, -1*10*1000*1000 );
} else {
ntTime.QuadPart = Int32x32To64( Seconds, 1*10*1000*1000 );
}
return ntTime;
} // SecondsToTime
LARGE_INTEGER
MinutesToTime (
IN ULONG Minutes,
IN BOOLEAN MakeNegative
)
/*++
Routine Description:
This routine converts a time interval specified in minutes to
the NT time base in 100s on nanoseconds.
Arguments:
Minutes - the interval in minutes.
MakeNegative - if TRUE, the time returned is a negative, i.e. relative
time.
Return Value:
LARGE_INTEGER - the interval in NT time.
--*/
{
PAGED_CODE( );
return SecondsToTime( 60*Minutes, MakeNegative );
} // MinutesToTime
ULONG
MultipleOfProcessors(
IN ULONG value
)
/*++
Routine Description:
This routine ensures the passed in value is a multiple of the number
of processors in the system. The value will be adjusted upward if
necessary.
Arguments:
value - the value to be adjusted
Return Value:
the adjusted value
--*/
{
value += SrvNumberOfProcessors - 1;
value /= SrvNumberOfProcessors;
value *= SrvNumberOfProcessors;
return value;
}