1441 lines
39 KiB
C
1441 lines
39 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
init.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module performs initialization for the AFD device driver.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
David Treadwell (davidtr) 21-Feb-1992
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "afdp.h"
|
|||
|
|
|||
|
#define REGISTRY_PARAMETERS L"Parameters"
|
|||
|
#define REGISTRY_AFD_INFORMATION L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Afd"
|
|||
|
#define REGISTRY_IRP_STACK_SIZE L"IrpStackSize"
|
|||
|
#define REGISTRY_PRIORITY_BOOST L"PriorityBoost"
|
|||
|
#define REGISTRY_IGNORE_PUSH_BIT L"IgnorePushBitOnReceives"
|
|||
|
#define REGISTRY_NO_RAW_SECURITY L"DisableRawSecurity"
|
|||
|
#define REGISTRY_NO_SHARED_ADDRESSES L"DisableAddressSharing"
|
|||
|
#define REGISTRY_NO_DIRECT_ACCEPTEX L"DisableDirectAcceptEx"
|
|||
|
#define REGISTRY_MAX_ACTIVE_TRANSMIT_FILE_COUNT L"MaxActiveTransmitFileCount"
|
|||
|
#define REGISTRY_ENABLE_DYNAMIC_BACKLOG L"EnableDynamicBacklog"
|
|||
|
#define REGISTRY_DISABLE_CHAINED_RECV L"DisableChainedReceive"
|
|||
|
#ifdef TDI_SERVICE_SEND_AND_DISCONNECT
|
|||
|
#define REGISTRY_USE_TDI_SEND_AND_DISCONNECT L"UseTdiSendAndDisconnect"
|
|||
|
#endif // TDI_SERVICE_SEND_AND_DISCONNECT
|
|||
|
#define REGISTRY_BUFFER_ALIGNMENT L"BufferAlignment"
|
|||
|
#define REGISTRY_VOLATILE_PARAMETERS L"VolatileParameters"
|
|||
|
|
|||
|
|
|||
|
#if DBG
|
|||
|
#define REGISTRY_DEBUG_FLAGS L"DebugFlags"
|
|||
|
#define REGISTRY_BREAK_ON_STARTUP L"BreakOnStartup"
|
|||
|
#define REGISTRY_USE_PRIVATE_ASSERT L"UsePrivateAssert"
|
|||
|
#endif
|
|||
|
|
|||
|
#if AFD_PERF_DBG
|
|||
|
#define REGISTRY_DISABLE_FAST_IO L"DisableFastIO"
|
|||
|
#define REGISTRY_DISABLE_CONN_REUSE L"DisableConnectionReuse"
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// A list of longwords that are configured by the registry.
|
|||
|
//
|
|||
|
|
|||
|
struct _AfdConfigInfo {
|
|||
|
PWCHAR RegistryValueName;
|
|||
|
PULONG Variable;
|
|||
|
} AfdConfigInfo[] = {
|
|||
|
{ L"LargeBufferSize", (PULONG)&AfdLargeBufferSize },
|
|||
|
{ L"LargeBufferListDepth", &AfdLargeBufferListDepth },
|
|||
|
{ L"MediumBufferSize", &AfdMediumBufferSize },
|
|||
|
{ L"MediumBufferListDepth", &AfdMediumBufferListDepth },
|
|||
|
{ L"SmallBufferSize", &AfdSmallBufferSize },
|
|||
|
{ L"SmallBufferListDepth", &AfdSmallBufferListDepth },
|
|||
|
{ L"BufferTagListDepth", &AfdBufferTagListDepth },
|
|||
|
{ L"FastSendDatagramThreshold", &AfdFastSendDatagramThreshold },
|
|||
|
{ L"PacketFragmentCopyThreshold", &AfdTPacketsCopyThreshold },
|
|||
|
{ L"StandardAddressLength", &AfdStandardAddressLength },
|
|||
|
{ L"DefaultReceiveWindow", &AfdReceiveWindowSize },
|
|||
|
{ L"DefaultSendWindow", &AfdSendWindowSize },
|
|||
|
{ L"TransmitIoLength", &AfdTransmitIoLength },
|
|||
|
{ L"MaxFastTransmit", &AfdMaxFastTransmit },
|
|||
|
{ L"MaxFastCopyTransmit", &AfdMaxFastCopyTransmit },
|
|||
|
{ L"MinimumDynamicBacklog", &AfdMinimumDynamicBacklog },
|
|||
|
{ L"MaximumDynamicBacklog", &AfdMaximumDynamicBacklog },
|
|||
|
{ L"DynamicBacklogGrowthDelta", &AfdDynamicBacklogGrowthDelta },
|
|||
|
{ L"DefaultPacketElementCount", &AfdDefaultTpInfoElementCount },
|
|||
|
{ L"TransmitWorker", &AfdDefaultTransmitWorker}
|
|||
|
},
|
|||
|
|
|||
|
AfdVolatileConfigInfo []= {
|
|||
|
{ L"FastSendDatagramThreshold", &AfdFastSendDatagramThreshold },
|
|||
|
{ L"PacketFragmentCopyThreshold", &AfdTPacketsCopyThreshold },
|
|||
|
{ L"TransmitIoLength", &AfdTransmitIoLength },
|
|||
|
{ L"MaxFastTransmit", &AfdMaxFastTransmit },
|
|||
|
{ L"MaxFastCopyTransmit", &AfdMaxFastCopyTransmit }
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
#define AFD_CONFIG_VAR_COUNT (sizeof(AfdConfigInfo) / sizeof(AfdConfigInfo[0]))
|
|||
|
#define AFD_VOLATILE_CONFIG_VAR_COUNT (sizeof(AfdVolatileConfigInfo) / sizeof(AfdVolatileConfigInfo[0]))
|
|||
|
|
|||
|
VOID
|
|||
|
AfdReadVolatileParameters (
|
|||
|
PVOID Parameter
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
AfdReleaseRegistryHandleWait (
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN PVOID Context
|
|||
|
);
|
|||
|
|
|||
|
ULONG
|
|||
|
AfdReadSingleParameter(
|
|||
|
IN HANDLE ParametersHandle,
|
|||
|
IN PWCHAR ValueName,
|
|||
|
IN LONG DefaultValue
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AfdOpenRegistry(
|
|||
|
IN PUNICODE_STRING BaseName,
|
|||
|
OUT PHANDLE ParametersHandle
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
AfdReadRegistry (
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
AfdUnload (
|
|||
|
IN PDRIVER_OBJECT DriverObject
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
DriverEntry (
|
|||
|
IN PDRIVER_OBJECT DriverObject,
|
|||
|
IN PUNICODE_STRING RegistryPath
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AfdCreateSecurityDescriptor(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AfdBuildDeviceAcl(
|
|||
|
OUT PACL *DeviceAcl
|
|||
|
);
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text( INIT, DriverEntry )
|
|||
|
#pragma alloc_text( PAGE, AfdReadSingleParameter )
|
|||
|
#pragma alloc_text( INIT, AfdOpenRegistry )
|
|||
|
#pragma alloc_text( INIT, AfdReadRegistry )
|
|||
|
#pragma alloc_text( INIT, AfdCreateSecurityDescriptor )
|
|||
|
#pragma alloc_text( INIT, AfdBuildDeviceAcl )
|
|||
|
#pragma alloc_text( PAGE, AfdUnload )
|
|||
|
#pragma alloc_text( PAGE, AfdReadVolatileParameters )
|
|||
|
#pragma alloc_text( PAGE, AfdReleaseRegistryHandleWait )
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
DriverEntry (
|
|||
|
IN PDRIVER_OBJECT DriverObject,
|
|||
|
IN PUNICODE_STRING RegistryPath
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the initialization routine for the AFD device driver.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DriverObject - Pointer to driver object created by the system.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The function value is the final status from the initialization operation.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS status;
|
|||
|
UNICODE_STRING deviceName;
|
|||
|
CLONG i;
|
|||
|
BOOLEAN success;
|
|||
|
ULONG size;
|
|||
|
|
|||
|
PAGED_CODE( );
|
|||
|
|
|||
|
//
|
|||
|
// Create the device object. (IoCreateDevice zeroes the memory
|
|||
|
// occupied by the object.)
|
|||
|
//
|
|||
|
// !!! Apply an ACL to the device object.
|
|||
|
//
|
|||
|
|
|||
|
RtlInitUnicodeString( &deviceName, AFD_DEVICE_NAME );
|
|||
|
|
|||
|
status = IoCreateDevice(
|
|||
|
DriverObject, // DriverObject
|
|||
|
0, // DeviceExtension
|
|||
|
&deviceName, // DeviceName
|
|||
|
FILE_DEVICE_NAMED_PIPE, // DeviceType
|
|||
|
0, // DeviceCharacteristics
|
|||
|
FALSE, // Exclusive
|
|||
|
&AfdDeviceObject // DeviceObject
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
if ( !NT_SUCCESS(status) ) {
|
|||
|
KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_ERROR_LEVEL,
|
|||
|
"AFD DriverEntry: unable to create device object: %lx\n",
|
|||
|
status ));
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
|
|||
|
AfdWorkQueueItem = IoAllocateWorkItem (AfdDeviceObject);
|
|||
|
if (AfdWorkQueueItem==NULL) {
|
|||
|
KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
|
|||
|
"AFD DriverEntry: unable to allocate work queue item\n" ));
|
|||
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
|
|||
|
KeInitializeEvent (&AfdContextWaitEvent, NotificationEvent, FALSE);
|
|||
|
|
|||
|
//
|
|||
|
// Create the security descriptor used for socket access checks.
|
|||
|
//
|
|||
|
status = AfdCreateSecurityDescriptor();
|
|||
|
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Initialize global data.
|
|||
|
//
|
|||
|
AfdInitializeData( );
|
|||
|
|
|||
|
//
|
|||
|
// Read registry information.
|
|||
|
// This may override hard-coded global
|
|||
|
// initialization above.
|
|||
|
//
|
|||
|
|
|||
|
AfdReadRegistry( );
|
|||
|
|
|||
|
#ifdef AFD_CHECK_ALIGNMENT
|
|||
|
AfdGlobalData = AFD_ALLOCATE_POOL_PRIORITY(
|
|||
|
NonPagedPool,
|
|||
|
FIELD_OFFSET (AFD_GLOBAL_DATA, BufferAlignmentTable[AfdAlignmentTableSize])
|
|||
|
// Note that although we have an array of UCHARs above
|
|||
|
// we do not need to align the array of ULONGs
|
|||
|
// since the UCHAR array size is aligned
|
|||
|
// to processor requirement.
|
|||
|
+ AfdAlignmentTableSize*sizeof(LONG),
|
|||
|
AFD_RESOURCE_POOL_TAG,
|
|||
|
HighPoolPriority
|
|||
|
);
|
|||
|
#else
|
|||
|
AfdGlobalData = AFD_ALLOCATE_POOL_PRIORITY(
|
|||
|
NonPagedPool,
|
|||
|
FIELD_OFFSET (AFD_GLOBAL_DATA, BufferAlignmentTable[AfdAlignmentTableSize]),
|
|||
|
AFD_RESOURCE_POOL_TAG,
|
|||
|
HighPoolPriority
|
|||
|
);
|
|||
|
#endif
|
|||
|
|
|||
|
if ( AfdGlobalData == NULL ) {
|
|||
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
|
|||
|
ExInitializeResourceLite( AfdResource );
|
|||
|
|
|||
|
AfdInitializeBufferManager();
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the AFD buffer lookaside lists. These must be
|
|||
|
// initialized *after* the registry data has been read.
|
|||
|
//
|
|||
|
|
|||
|
size = AfdCalculateBufferSize (AfdLargeBufferSize, AfdStandardAddressLength);
|
|||
|
ExInitializeNPagedLookasideList(
|
|||
|
&AfdLookasideLists->LargeBufferList,
|
|||
|
AfdAllocateBuffer,
|
|||
|
AfdFreeBuffer,
|
|||
|
0,
|
|||
|
size,
|
|||
|
AFD_DATA_BUFFER_POOL_TAG,
|
|||
|
(USHORT)AfdLargeBufferListDepth
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Make sure that if as the result of alignment the allocation size is adjusted
|
|||
|
// to equal to the larger one, the actual buffer sizes are adjusted as well.
|
|||
|
// This is necessary to avoid confusing block allocator which determines
|
|||
|
// buffer size based on the allocation size passed by the lookaside list
|
|||
|
// code.
|
|||
|
//
|
|||
|
size = AfdCalculateBufferSize (AfdMediumBufferSize, AfdStandardAddressLength);
|
|||
|
if (size==AfdLookasideLists->LargeBufferList.L.Size) {
|
|||
|
AfdMediumBufferSize = AfdLargeBufferSize;
|
|||
|
}
|
|||
|
else {
|
|||
|
ASSERT (size<AfdLookasideLists->LargeBufferList.L.Size);
|
|||
|
}
|
|||
|
ExInitializeNPagedLookasideList(
|
|||
|
&AfdLookasideLists->MediumBufferList,
|
|||
|
AfdAllocateBuffer,
|
|||
|
AfdFreeBuffer,
|
|||
|
0,
|
|||
|
size,
|
|||
|
AFD_DATA_BUFFER_POOL_TAG,
|
|||
|
(USHORT)AfdMediumBufferListDepth
|
|||
|
);
|
|||
|
|
|||
|
size = AfdCalculateBufferSize (AfdSmallBufferSize, AfdStandardAddressLength);
|
|||
|
if (size==AfdLookasideLists->MediumBufferList.L.Size) {
|
|||
|
AfdSmallBufferSize = AfdMediumBufferSize;
|
|||
|
}
|
|||
|
else {
|
|||
|
ASSERT (size<AfdLookasideLists->MediumBufferList.L.Size);
|
|||
|
}
|
|||
|
ExInitializeNPagedLookasideList(
|
|||
|
&AfdLookasideLists->SmallBufferList,
|
|||
|
AfdAllocateBuffer,
|
|||
|
AfdFreeBuffer,
|
|||
|
0,
|
|||
|
size,
|
|||
|
AFD_DATA_BUFFER_POOL_TAG,
|
|||
|
(USHORT)AfdSmallBufferListDepth
|
|||
|
);
|
|||
|
|
|||
|
ExInitializeNPagedLookasideList(
|
|||
|
&AfdLookasideLists->BufferTagList,
|
|||
|
AfdAllocateBufferTag,
|
|||
|
AfdFreeBufferTag,
|
|||
|
0,
|
|||
|
sizeof (AFD_BUFFER_TAG),
|
|||
|
AFD_DATA_BUFFER_POOL_TAG,
|
|||
|
(USHORT)AfdBufferTagListDepth
|
|||
|
);
|
|||
|
|
|||
|
ExInitializeNPagedLookasideList(
|
|||
|
&AfdLookasideLists->TpInfoList,
|
|||
|
AfdAllocateTpInfo,
|
|||
|
AfdFreeTpInfo,
|
|||
|
0,
|
|||
|
AfdComputeTpInfoSize (AfdDefaultTpInfoElementCount,
|
|||
|
AFD_TP_MIN_SEND_IRPS,
|
|||
|
AfdIrpStackSize-1),
|
|||
|
AFD_TRANSMIT_INFO_POOL_TAG,
|
|||
|
0
|
|||
|
);
|
|||
|
|
|||
|
ExInitializeNPagedLookasideList(
|
|||
|
&AfdLookasideLists->RemoteAddrList,
|
|||
|
AfdAllocateRemoteAddress,
|
|||
|
AfdFreeRemoteAddress,
|
|||
|
0,
|
|||
|
AfdStandardAddressLength,
|
|||
|
AFD_REMOTE_ADDRESS_POOL_TAG,
|
|||
|
(USHORT)AfdBufferTagListDepth
|
|||
|
);
|
|||
|
|
|||
|
AfdLookasideLists->TrimFlags = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize group ID manager.
|
|||
|
//
|
|||
|
|
|||
|
success = AfdInitializeGroup();
|
|||
|
if ( !success ) {
|
|||
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the driver object for this file system driver.
|
|||
|
//
|
|||
|
|
|||
|
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
|
|||
|
DriverObject->MajorFunction[i] = AfdDispatch;
|
|||
|
}
|
|||
|
//
|
|||
|
// Special case for IRP_MJ_DEVICE_CONTROL since it is
|
|||
|
// the most often used function in AFD.
|
|||
|
//
|
|||
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
|
|||
|
AfdDispatchDeviceControl;
|
|||
|
|
|||
|
DriverObject->FastIoDispatch = &AfdFastIoDispatch;
|
|||
|
DriverObject->DriverUnload = AfdUnload;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize our device object.
|
|||
|
//
|
|||
|
|
|||
|
AfdDeviceObject->Flags |= DO_DIRECT_IO;
|
|||
|
AfdDeviceObject->StackSize = AfdIrpStackSize;
|
|||
|
|
|||
|
//
|
|||
|
// Remember a pointer to the system process. We'll use this pointer
|
|||
|
// for KeAttachProcess() calls so that we can open handles in the
|
|||
|
// context of the system process.
|
|||
|
//
|
|||
|
|
|||
|
AfdSystemProcess = (PKPROCESS)IoGetCurrentProcess();
|
|||
|
|
|||
|
//
|
|||
|
// Start notification for volatile parameters if necessary.
|
|||
|
//
|
|||
|
if (AfdParametersNotifyHandle) {
|
|||
|
AfdReadVolatileParameters (NULL);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Tell MM that it can page all of AFD it is desires. We will reset
|
|||
|
// to normal paging of AFD code as soon as an AFD endpoint is
|
|||
|
// opened.
|
|||
|
//
|
|||
|
|
|||
|
AfdLoaded = NULL;
|
|||
|
|
|||
|
MmPageEntireDriver( DriverEntry );
|
|||
|
|
|||
|
return (status);
|
|||
|
|
|||
|
error_exit:
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Terminate the group ID manager.
|
|||
|
//
|
|||
|
|
|||
|
AfdTerminateGroup();
|
|||
|
|
|||
|
if (AfdAdminSecurityDescriptor!=NULL) {
|
|||
|
ExFreePool (AfdAdminSecurityDescriptor);
|
|||
|
AfdAdminSecurityDescriptor = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if( AfdGlobalData != NULL ) {
|
|||
|
|
|||
|
ExDeleteNPagedLookasideList( &AfdLookasideLists->LargeBufferList );
|
|||
|
ExDeleteNPagedLookasideList( &AfdLookasideLists->MediumBufferList );
|
|||
|
ExDeleteNPagedLookasideList( &AfdLookasideLists->SmallBufferList );
|
|||
|
ExDeleteNPagedLookasideList( &AfdLookasideLists->BufferTagList );
|
|||
|
ExDeleteNPagedLookasideList( &AfdLookasideLists->TpInfoList );
|
|||
|
ExDeleteNPagedLookasideList( &AfdLookasideLists->RemoteAddrList );
|
|||
|
|
|||
|
ExDeleteResourceLite( AfdResource );
|
|||
|
|
|||
|
AFD_FREE_POOL(
|
|||
|
AfdGlobalData,
|
|||
|
AFD_RESOURCE_POOL_TAG
|
|||
|
);
|
|||
|
AfdGlobalData = NULL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (AfdWorkQueueItem!=NULL) {
|
|||
|
IoFreeWorkItem (AfdWorkQueueItem);
|
|||
|
AfdWorkQueueItem = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if (AfdDeviceObject!=NULL) {
|
|||
|
IoDeleteDevice(AfdDeviceObject);
|
|||
|
AfdDeviceObject = NULL;
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
|
|||
|
} // DriverEntry
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
AfdUnload (
|
|||
|
IN PDRIVER_OBJECT DriverObject
|
|||
|
)
|
|||
|
{
|
|||
|
|
|||
|
PLIST_ENTRY listEntry;
|
|||
|
KEVENT event;
|
|||
|
BOOLEAN wait;
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER( DriverObject );
|
|||
|
|
|||
|
PAGED_CODE( );
|
|||
|
|
|||
|
KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
|
|||
|
"AfdUnload called.\n" ));
|
|||
|
|
|||
|
if (AfdParametersNotifyHandle!=NULL) {
|
|||
|
KeEnterCriticalRegion ();
|
|||
|
ExAcquireResourceExclusiveLite( AfdResource, TRUE );
|
|||
|
ZwClose (AfdParametersNotifyHandle);
|
|||
|
AfdParametersNotifyHandle = NULL;
|
|||
|
KeInitializeEvent( &event, SynchronizationEvent, FALSE );
|
|||
|
AfdParametersUnloadEvent = &event;
|
|||
|
ExReleaseResourceLite( AfdResource );
|
|||
|
KeLeaveCriticalRegion ();
|
|||
|
}
|
|||
|
//
|
|||
|
// Check if AFD has already cleaned up all endpoints and
|
|||
|
// is ready to get unloaded.
|
|||
|
//
|
|||
|
KeEnterCriticalRegion ();
|
|||
|
ExAcquireResourceExclusiveLite( AfdResource, TRUE );
|
|||
|
if (AfdLoaded!=NULL) {
|
|||
|
//
|
|||
|
// Some work still needs to be done. Setup the wait.
|
|||
|
//
|
|||
|
ASSERT (AfdLoaded==(PKEVENT)1);
|
|||
|
KeInitializeEvent( &event, SynchronizationEvent, FALSE );
|
|||
|
AfdLoaded = &event;
|
|||
|
wait = TRUE;
|
|||
|
}
|
|||
|
else
|
|||
|
wait = FALSE;
|
|||
|
|
|||
|
ExReleaseResourceLite( AfdResource );
|
|||
|
KeLeaveCriticalRegion ();
|
|||
|
|
|||
|
if (wait) {
|
|||
|
NTSTATUS status;
|
|||
|
KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
|
|||
|
"AfdUnload: Waiting for endpoints to cleanup...\n"));
|
|||
|
status = KeWaitForSingleObject( (PVOID)&event, Executive, KernelMode, FALSE, NULL );
|
|||
|
ASSERT (NT_SUCCESS (status));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Kill the transport info list.
|
|||
|
//
|
|||
|
|
|||
|
while( !IsListEmpty( &AfdTransportInfoListHead ) ) {
|
|||
|
PAFD_TRANSPORT_INFO transportInfo;
|
|||
|
|
|||
|
listEntry = RemoveHeadList( &AfdTransportInfoListHead );
|
|||
|
|
|||
|
transportInfo = CONTAINING_RECORD(
|
|||
|
listEntry,
|
|||
|
AFD_TRANSPORT_INFO,
|
|||
|
TransportInfoListEntry
|
|||
|
);
|
|||
|
|
|||
|
ASSERT (transportInfo->ReferenceCount == 1);
|
|||
|
|
|||
|
|
|||
|
AFD_FREE_POOL(
|
|||
|
transportInfo,
|
|||
|
AFD_TRANSPORT_INFO_POOL_TAG
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Free address list and associated structures
|
|||
|
//
|
|||
|
AfdDeregisterPnPHandlers (NULL);
|
|||
|
|
|||
|
if (AfdAddressListLock) {
|
|||
|
|
|||
|
ExDeleteResourceLite( AfdAddressListLock );
|
|||
|
|
|||
|
AFD_FREE_POOL(
|
|||
|
AfdAddressListLock,
|
|||
|
AFD_RESOURCE_POOL_TAG
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Do some cleanup for SAN
|
|||
|
//
|
|||
|
if (IoCompletionObjectType!=NULL) {
|
|||
|
ObDereferenceObject (IoCompletionObjectType);
|
|||
|
IoCompletionObjectType = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if (AfdAdminSecurityDescriptor!=NULL) {
|
|||
|
ExFreePool (AfdAdminSecurityDescriptor);
|
|||
|
AfdAdminSecurityDescriptor = NULL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Terminate the group ID manager.
|
|||
|
//
|
|||
|
|
|||
|
AfdTerminateGroup();
|
|||
|
#if DBG || REFERENCE_DEBUG
|
|||
|
AfdFreeDebugData ();
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Kill the lookaside lists and resouce in the global data
|
|||
|
//
|
|||
|
|
|||
|
if( AfdGlobalData != NULL ) {
|
|||
|
|
|||
|
ExDeleteNPagedLookasideList( &AfdLookasideLists->LargeBufferList );
|
|||
|
ExDeleteNPagedLookasideList( &AfdLookasideLists->MediumBufferList );
|
|||
|
ExDeleteNPagedLookasideList( &AfdLookasideLists->SmallBufferList );
|
|||
|
ExDeleteNPagedLookasideList( &AfdLookasideLists->BufferTagList );
|
|||
|
ExDeleteNPagedLookasideList( &AfdLookasideLists->TpInfoList );
|
|||
|
ExDeleteNPagedLookasideList( &AfdLookasideLists->RemoteAddrList );
|
|||
|
|
|||
|
ExDeleteResourceLite( AfdResource );
|
|||
|
|
|||
|
AFD_FREE_POOL(
|
|||
|
AfdGlobalData,
|
|||
|
AFD_RESOURCE_POOL_TAG
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Delete our device object.
|
|||
|
//
|
|||
|
|
|||
|
IoDeleteDevice( AfdDeviceObject );
|
|||
|
|
|||
|
} // AfdUnload
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
AfdReadRegistry (
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Reads the AFD section of the registry. Any values listed in the
|
|||
|
registry override defaults.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None -- if anything fails, the default value is used.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HANDLE parametersHandle;
|
|||
|
NTSTATUS status;
|
|||
|
ULONG stackSize;
|
|||
|
ULONG priorityBoost;
|
|||
|
ULONG bufferAlignment;
|
|||
|
UNICODE_STRING registryPath;
|
|||
|
ULONG i;
|
|||
|
|
|||
|
PAGED_CODE( );
|
|||
|
|
|||
|
RtlInitUnicodeString( ®istryPath, REGISTRY_AFD_INFORMATION );
|
|||
|
|
|||
|
status = AfdOpenRegistry( ®istryPath, ¶metersHandle );
|
|||
|
|
|||
|
if (status != STATUS_SUCCESS) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
//
|
|||
|
// Read the debug flags from the registry.
|
|||
|
//
|
|||
|
|
|||
|
AfdDebug = AfdReadSingleParameter(
|
|||
|
parametersHandle,
|
|||
|
REGISTRY_DEBUG_FLAGS,
|
|||
|
AfdDebug
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Force a breakpoint if so requested.
|
|||
|
//
|
|||
|
|
|||
|
if( AfdReadSingleParameter(
|
|||
|
parametersHandle,
|
|||
|
REGISTRY_BREAK_ON_STARTUP,
|
|||
|
0 ) != 0 ) {
|
|||
|
DbgBreakPoint();
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Enable private assert function if requested.
|
|||
|
//
|
|||
|
|
|||
|
AfdUsePrivateAssert = AfdReadSingleParameter(
|
|||
|
parametersHandle,
|
|||
|
REGISTRY_USE_PRIVATE_ASSERT,
|
|||
|
(LONG)AfdUsePrivateAssert
|
|||
|
) != 0;
|
|||
|
#endif
|
|||
|
|
|||
|
#if AFD_PERF_DBG
|
|||
|
//
|
|||
|
// Read a flag from the registry that allows us to disable Fast IO.
|
|||
|
//
|
|||
|
|
|||
|
AfdDisableFastIo = AfdReadSingleParameter(
|
|||
|
parametersHandle,
|
|||
|
REGISTRY_DISABLE_FAST_IO,
|
|||
|
(LONG)AfdDisableFastIo
|
|||
|
) != 0;
|
|||
|
|
|||
|
if( AfdDisableFastIo ) {
|
|||
|
|
|||
|
KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
|
|||
|
"AFD: Fast IO disabled\n" ));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Read a flag from the registry that allows us to disable connection
|
|||
|
// reuse.
|
|||
|
//
|
|||
|
|
|||
|
AfdDisableConnectionReuse = AfdReadSingleParameter(
|
|||
|
parametersHandle,
|
|||
|
REGISTRY_DISABLE_CONN_REUSE,
|
|||
|
(LONG)AfdDisableConnectionReuse
|
|||
|
) != 0;
|
|||
|
|
|||
|
if( AfdDisableConnectionReuse ) {
|
|||
|
|
|||
|
KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
|
|||
|
"AFD: Connection Reuse disabled\n" ));
|
|||
|
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Read the stack size and priority boost values from the registry.
|
|||
|
//
|
|||
|
|
|||
|
stackSize = AfdReadSingleParameter(
|
|||
|
parametersHandle,
|
|||
|
REGISTRY_IRP_STACK_SIZE,
|
|||
|
(ULONG)AfdIrpStackSize
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// We do not support more than 63 layers below us.
|
|||
|
// (The system allows for 127, but some can be sitting above us
|
|||
|
// as well.
|
|||
|
//
|
|||
|
if ( stackSize > 64 ) {
|
|||
|
stackSize = 64;
|
|||
|
}
|
|||
|
|
|||
|
if (stackSize<2) {
|
|||
|
//
|
|||
|
// Can't be less than two since we have to call
|
|||
|
// at least one driver below us.
|
|||
|
//
|
|||
|
stackSize = 2;
|
|||
|
}
|
|||
|
|
|||
|
AfdIrpStackSize = (CCHAR)stackSize;
|
|||
|
|
|||
|
priorityBoost = AfdReadSingleParameter(
|
|||
|
parametersHandle,
|
|||
|
REGISTRY_PRIORITY_BOOST,
|
|||
|
(ULONG)AfdPriorityBoost
|
|||
|
);
|
|||
|
|
|||
|
if ( priorityBoost > 16 ) {
|
|||
|
priorityBoost = AFD_DEFAULT_PRIORITY_BOOST;
|
|||
|
}
|
|||
|
|
|||
|
AfdPriorityBoost = (CCHAR)priorityBoost;
|
|||
|
|
|||
|
//
|
|||
|
// Read other config variables from the registry.
|
|||
|
//
|
|||
|
|
|||
|
for ( i = 0; i < AFD_CONFIG_VAR_COUNT; i++ ) {
|
|||
|
|
|||
|
*AfdConfigInfo[i].Variable =
|
|||
|
AfdReadSingleParameter(
|
|||
|
parametersHandle,
|
|||
|
AfdConfigInfo[i].RegistryValueName,
|
|||
|
*AfdConfigInfo[i].Variable
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Validate standard buffer sizes.
|
|||
|
// (we use buffer for KAPC or WORK_QUEUE_ITEM storage
|
|||
|
// in fast transmit file processing).
|
|||
|
//
|
|||
|
if (AfdSmallBufferSize<max (sizeof(KAPC),sizeof (WORK_QUEUE_ITEM)))
|
|||
|
AfdSmallBufferSize = max (sizeof(KAPC),sizeof (WORK_QUEUE_ITEM));
|
|||
|
if (AfdMediumBufferSize<AfdSmallBufferSize)
|
|||
|
AfdMediumBufferSize = AfdSmallBufferSize;
|
|||
|
if (AfdLargeBufferSize<AfdMediumBufferSize)
|
|||
|
AfdLargeBufferSize = AfdMediumBufferSize;
|
|||
|
|
|||
|
AfdIgnorePushBitOnReceives = AfdReadSingleParameter(
|
|||
|
parametersHandle,
|
|||
|
REGISTRY_IGNORE_PUSH_BIT,
|
|||
|
(LONG)AfdIgnorePushBitOnReceives
|
|||
|
)!=0;
|
|||
|
|
|||
|
|
|||
|
AfdDisableRawSecurity = AfdReadSingleParameter(
|
|||
|
parametersHandle,
|
|||
|
REGISTRY_NO_RAW_SECURITY,
|
|||
|
(LONG)AfdDisableRawSecurity
|
|||
|
)!=0;
|
|||
|
|
|||
|
AfdDontShareAddresses = AfdReadSingleParameter(
|
|||
|
parametersHandle,
|
|||
|
REGISTRY_NO_SHARED_ADDRESSES,
|
|||
|
(LONG)AfdDontShareAddresses
|
|||
|
)!=0;
|
|||
|
|
|||
|
AfdDisableDirectSuperAccept = AfdReadSingleParameter(
|
|||
|
parametersHandle,
|
|||
|
REGISTRY_NO_DIRECT_ACCEPTEX,
|
|||
|
(LONG)AfdDisableDirectSuperAccept
|
|||
|
)!=0;
|
|||
|
|
|||
|
AfdDisableChainedReceive = AfdReadSingleParameter(
|
|||
|
parametersHandle,
|
|||
|
REGISTRY_DISABLE_CHAINED_RECV,
|
|||
|
(LONG)AfdDisableChainedReceive
|
|||
|
) != 0;
|
|||
|
|
|||
|
#ifdef TDI_SERVICE_SEND_AND_DISCONNECT
|
|||
|
AfdUseTdiSendAndDisconnect = AfdReadSingleParameter(
|
|||
|
parametersHandle,
|
|||
|
REGISTRY_USE_TDI_SEND_AND_DISCONNECT,
|
|||
|
(LONG)AfdUseTdiSendAndDisconnect
|
|||
|
) != 0;
|
|||
|
#endif //TDI_SERVICE_SEND_AND_DISCONNECT
|
|||
|
if( MmIsThisAnNtAsSystem() ) {
|
|||
|
|
|||
|
//
|
|||
|
// On the NT Server product, make the maximum active TransmitFile
|
|||
|
// count configurable. This value is fixed (not configurable) on
|
|||
|
// the NT Workstation product.
|
|||
|
//
|
|||
|
|
|||
|
AfdMaxActiveTransmitFileCount = AfdReadSingleParameter(
|
|||
|
parametersHandle,
|
|||
|
REGISTRY_MAX_ACTIVE_TRANSMIT_FILE_COUNT,
|
|||
|
(LONG)AfdMaxActiveTransmitFileCount
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Dynamic backlog is only possible on NT Server.
|
|||
|
//
|
|||
|
|
|||
|
AfdEnableDynamicBacklog = AfdReadSingleParameter(
|
|||
|
parametersHandle,
|
|||
|
REGISTRY_ENABLE_DYNAMIC_BACKLOG,
|
|||
|
(LONG)AfdEnableDynamicBacklog
|
|||
|
) != 0;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
AfdEnableDynamicBacklog = FALSE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
switch (AfdDefaultTransmitWorker) {
|
|||
|
case AFD_TF_USE_SYSTEM_THREAD:
|
|||
|
case AFD_TF_USE_KERNEL_APC:
|
|||
|
break;
|
|||
|
default:
|
|||
|
KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_ERROR_LEVEL,
|
|||
|
"AFD: Invalid TransmitWorker registry parameter value: %ld\n"
|
|||
|
"AFD; Using default - %ld\n",
|
|||
|
AfdDefaultTransmitWorker,
|
|||
|
AFD_DEFAULT_TRANSMIT_WORKER));
|
|||
|
AfdDefaultTransmitWorker = AFD_DEFAULT_TRANSMIT_WORKER;
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
bufferAlignment = AfdReadSingleParameter(
|
|||
|
parametersHandle,
|
|||
|
REGISTRY_BUFFER_ALIGNMENT,
|
|||
|
(LONG)AfdBufferAlignment
|
|||
|
);
|
|||
|
if (bufferAlignment!=AfdBufferAlignment) {
|
|||
|
if (bufferAlignment<AFD_MINIMUM_BUFFER_ALIGNMENT ||
|
|||
|
bufferAlignment>PAGE_SIZE ||
|
|||
|
(bufferAlignment & (bufferAlignment-1))!=0) {
|
|||
|
KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_ERROR_LEVEL,
|
|||
|
"AFD: Invalid %ls registry parameter value: %ld\n"
|
|||
|
"AFD; Using default - %ld\n",
|
|||
|
REGISTRY_BUFFER_ALIGNMENT,
|
|||
|
bufferAlignment,
|
|||
|
AfdBufferAlignment));
|
|||
|
}
|
|||
|
else {
|
|||
|
AfdBufferAlignment = bufferAlignment;
|
|||
|
AfdAlignmentTableSize = AfdBufferAlignment/AFD_MINIMUM_BUFFER_ALIGNMENT;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
AfdVolatileConfig = AfdReadSingleParameter (
|
|||
|
parametersHandle,
|
|||
|
REGISTRY_VOLATILE_PARAMETERS,
|
|||
|
(LONG)AfdVolatileConfig)!=0;
|
|||
|
if (AfdVolatileConfig) {
|
|||
|
AfdParametersNotifyHandle = parametersHandle;
|
|||
|
ExInitializeWorkItem (&AfdParametersNotifyWorker, AfdReadVolatileParameters, NULL);
|
|||
|
}
|
|||
|
else {
|
|||
|
ZwClose( parametersHandle );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Need to recalculate size of the page-long buffer if standard
|
|||
|
// address length has changed
|
|||
|
//
|
|||
|
if (AfdStandardAddressLength!=AFD_DEFAULT_STD_ADDRESS_LENGTH) {
|
|||
|
CLONG oldBufferLengthForOnePage = AfdBufferLengthForOnePage;
|
|||
|
|
|||
|
AfdBufferOverhead = AfdCalculateBufferSize( PAGE_SIZE, AfdStandardAddressLength) - PAGE_SIZE;
|
|||
|
AfdBufferLengthForOnePage = ALIGN_DOWN_A(
|
|||
|
PAGE_SIZE-AfdBufferOverhead,
|
|||
|
AFD_MINIMUM_BUFFER_ALIGNMENT);
|
|||
|
if (AfdLargeBufferSize==oldBufferLengthForOnePage) {
|
|||
|
AfdLargeBufferSize = AfdBufferLengthForOnePage;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
} // AfdReadRegistry
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AfdOpenRegistry(
|
|||
|
IN PUNICODE_STRING BaseName,
|
|||
|
OUT PHANDLE ParametersHandle
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called by AFD to open the registry. If the registry
|
|||
|
tree exists, then it opens it and returns an error. If not, it
|
|||
|
creates the appropriate keys in the registry, opens it, and
|
|||
|
returns STATUS_SUCCESS.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BaseName - Where in the registry to start looking for the information.
|
|||
|
|
|||
|
LinkageHandle - Returns the handle used to read linkage information.
|
|||
|
|
|||
|
ParametersHandle - Returns the handle used to read other
|
|||
|
parameters.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The status of the request.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
HANDLE configHandle;
|
|||
|
NTSTATUS status;
|
|||
|
PWSTR parametersString = REGISTRY_PARAMETERS;
|
|||
|
UNICODE_STRING parametersKeyName;
|
|||
|
OBJECT_ATTRIBUTES objectAttributes;
|
|||
|
ULONG disposition;
|
|||
|
|
|||
|
PAGED_CODE( );
|
|||
|
|
|||
|
//
|
|||
|
// Open the registry for the initial string.
|
|||
|
//
|
|||
|
|
|||
|
InitializeObjectAttributes(
|
|||
|
&objectAttributes,
|
|||
|
BaseName, // name
|
|||
|
OBJ_CASE_INSENSITIVE, // attributes
|
|||
|
NULL, // root
|
|||
|
NULL // security descriptor
|
|||
|
);
|
|||
|
|
|||
|
status = ZwCreateKey(
|
|||
|
&configHandle,
|
|||
|
KEY_WRITE,
|
|||
|
&objectAttributes,
|
|||
|
0, // title index
|
|||
|
NULL, // class
|
|||
|
0, // create options
|
|||
|
&disposition // disposition
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
return STATUS_UNSUCCESSFUL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now open the parameters key.
|
|||
|
//
|
|||
|
|
|||
|
RtlInitUnicodeString (¶metersKeyName, parametersString);
|
|||
|
|
|||
|
InitializeObjectAttributes(
|
|||
|
&objectAttributes,
|
|||
|
¶metersKeyName, // name
|
|||
|
OBJ_CASE_INSENSITIVE, // attributes
|
|||
|
configHandle, // root
|
|||
|
NULL // security descriptor
|
|||
|
);
|
|||
|
|
|||
|
status = ZwOpenKey(
|
|||
|
ParametersHandle,
|
|||
|
KEY_READ,
|
|||
|
&objectAttributes
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
|
|||
|
ZwClose( configHandle );
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// All keys successfully opened or created.
|
|||
|
//
|
|||
|
|
|||
|
ZwClose( configHandle );
|
|||
|
return STATUS_SUCCESS;
|
|||
|
|
|||
|
} // AfdOpenRegistry
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
AfdReadSingleParameter(
|
|||
|
IN HANDLE ParametersHandle,
|
|||
|
IN PWCHAR ValueName,
|
|||
|
IN LONG DefaultValue
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called by AFD to read a single parameter
|
|||
|
from the registry. If the parameter is found it is stored
|
|||
|
in Data.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ParametersHandle - A pointer to the open registry.
|
|||
|
|
|||
|
ValueName - The name of the value to search for.
|
|||
|
|
|||
|
DefaultValue - The default value.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The value to use; will be the default if the value is not
|
|||
|
found or is not in the correct range.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
static ULONG informationBuffer[32]; // declare ULONG to get it aligned
|
|||
|
PKEY_VALUE_FULL_INFORMATION information =
|
|||
|
(PKEY_VALUE_FULL_INFORMATION)informationBuffer;
|
|||
|
UNICODE_STRING valueKeyName;
|
|||
|
ULONG informationLength;
|
|||
|
LONG returnValue;
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
PAGED_CODE( );
|
|||
|
|
|||
|
RtlInitUnicodeString( &valueKeyName, ValueName );
|
|||
|
|
|||
|
status = ZwQueryValueKey(
|
|||
|
ParametersHandle,
|
|||
|
&valueKeyName,
|
|||
|
KeyValueFullInformation,
|
|||
|
(PVOID)information,
|
|||
|
sizeof (informationBuffer),
|
|||
|
&informationLength
|
|||
|
);
|
|||
|
|
|||
|
if ((status == STATUS_SUCCESS) && (information->DataLength == sizeof(ULONG))) {
|
|||
|
|
|||
|
RtlMoveMemory(
|
|||
|
(PVOID)&returnValue,
|
|||
|
((PUCHAR)information) + information->DataOffset,
|
|||
|
sizeof(ULONG)
|
|||
|
);
|
|||
|
|
|||
|
if (returnValue < 0) {
|
|||
|
|
|||
|
returnValue = DefaultValue;
|
|||
|
|
|||
|
}
|
|||
|
else if (returnValue!=DefaultValue) {
|
|||
|
DbgPrint ("AFD: Read %ls from the registry, value: 0x%lx (%s: 0x%lx))\n",
|
|||
|
ValueName, returnValue,
|
|||
|
AfdVolatileConfig ? "previous" : "default",
|
|||
|
DefaultValue);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
returnValue = DefaultValue;
|
|||
|
}
|
|||
|
|
|||
|
return returnValue;
|
|||
|
|
|||
|
} // AfdReadSingleParameter
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AfdBuildDeviceAcl(
|
|||
|
OUT PACL *DeviceAcl
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine builds an ACL which gives Administrators, LocalSystem,
|
|||
|
and NetworkService principals full access. All other principals have no access.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DeviceAcl - Output pointer to the new ACL.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS or an appropriate error code.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PGENERIC_MAPPING GenericMapping;
|
|||
|
ULONG AclLength;
|
|||
|
NTSTATUS Status;
|
|||
|
ACCESS_MASK AccessMask = GENERIC_ALL;
|
|||
|
PACL NewAcl;
|
|||
|
|
|||
|
//
|
|||
|
// Enable access to all the globally defined SIDs
|
|||
|
//
|
|||
|
|
|||
|
GenericMapping = IoGetFileObjectGenericMapping();
|
|||
|
|
|||
|
RtlMapGenericMask( &AccessMask, GenericMapping );
|
|||
|
|
|||
|
AclLength = sizeof( ACL ) +
|
|||
|
3 * FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
|
|||
|
RtlLengthSid( SeExports->SeAliasAdminsSid ) +
|
|||
|
RtlLengthSid( SeExports->SeLocalSystemSid ) +
|
|||
|
RtlLengthSid( SeExports->SeNetworkServiceSid );
|
|||
|
|
|||
|
NewAcl = AFD_ALLOCATE_POOL_PRIORITY (
|
|||
|
PagedPool,
|
|||
|
AclLength,
|
|||
|
AFD_SECURITY_POOL_TAG,
|
|||
|
HighPoolPriority
|
|||
|
);
|
|||
|
|
|||
|
if (NewAcl == NULL) {
|
|||
|
return( STATUS_INSUFFICIENT_RESOURCES );
|
|||
|
}
|
|||
|
|
|||
|
Status = RtlCreateAcl (NewAcl, AclLength, ACL_REVISION );
|
|||
|
|
|||
|
if (!NT_SUCCESS( Status )) {
|
|||
|
AFD_FREE_POOL(
|
|||
|
NewAcl,
|
|||
|
AFD_SECURITY_POOL_TAG
|
|||
|
);
|
|||
|
return( Status );
|
|||
|
}
|
|||
|
|
|||
|
Status = RtlAddAccessAllowedAce (
|
|||
|
NewAcl,
|
|||
|
ACL_REVISION2,
|
|||
|
AccessMask,
|
|||
|
SeExports->SeAliasAdminsSid
|
|||
|
);
|
|||
|
|
|||
|
ASSERT( NT_SUCCESS( Status ));
|
|||
|
|
|||
|
Status = RtlAddAccessAllowedAce (
|
|||
|
NewAcl,
|
|||
|
ACL_REVISION2,
|
|||
|
AccessMask,
|
|||
|
SeExports->SeLocalSystemSid
|
|||
|
);
|
|||
|
|
|||
|
ASSERT( NT_SUCCESS( Status ));
|
|||
|
|
|||
|
Status = RtlAddAccessAllowedAce (
|
|||
|
NewAcl,
|
|||
|
ACL_REVISION2,
|
|||
|
AccessMask,
|
|||
|
SeExports->SeNetworkServiceSid
|
|||
|
);
|
|||
|
|
|||
|
ASSERT( NT_SUCCESS( Status ));
|
|||
|
|
|||
|
*DeviceAcl = NewAcl;
|
|||
|
|
|||
|
return( STATUS_SUCCESS );
|
|||
|
|
|||
|
} // AfdBuildDeviceAcl
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AfdCreateSecurityDescriptor(
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine creates a security descriptor which gives access
|
|||
|
only to certain priviliged accounts. This descriptor is used
|
|||
|
to access check raw endpoint opens and exclisive access to transport
|
|||
|
addresses.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS or an appropriate error code.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PACL devAcl = NULL;
|
|||
|
NTSTATUS status;
|
|||
|
BOOLEAN memoryAllocated = FALSE;
|
|||
|
PSECURITY_DESCRIPTOR afdSecurityDescriptor;
|
|||
|
ULONG afdSecurityDescriptorLength;
|
|||
|
CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
|
|||
|
PSECURITY_DESCRIPTOR localSecurityDescriptor =
|
|||
|
(PSECURITY_DESCRIPTOR) &buffer;
|
|||
|
PSECURITY_DESCRIPTOR localAfdAdminSecurityDescriptor;
|
|||
|
SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Get a pointer to the security descriptor from the AFD device object.
|
|||
|
//
|
|||
|
status = ObGetObjectSecurity(
|
|||
|
AfdDeviceObject,
|
|||
|
&afdSecurityDescriptor,
|
|||
|
&memoryAllocated
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_ERROR_LEVEL,
|
|||
|
"AFD: Unable to get security descriptor, error: %x\n",
|
|||
|
status
|
|||
|
));
|
|||
|
ASSERT(memoryAllocated == FALSE);
|
|||
|
return(status);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Build a local security descriptor with an ACL giving only
|
|||
|
// certain priviliged accounts.
|
|||
|
//
|
|||
|
status = AfdBuildDeviceAcl(&devAcl);
|
|||
|
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_ERROR_LEVEL,
|
|||
|
"AFD: Unable to create Raw ACL, error: %x\n", status));
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
|
|||
|
(VOID) RtlCreateSecurityDescriptor(
|
|||
|
localSecurityDescriptor,
|
|||
|
SECURITY_DESCRIPTOR_REVISION
|
|||
|
);
|
|||
|
|
|||
|
(VOID) RtlSetDaclSecurityDescriptor(
|
|||
|
localSecurityDescriptor,
|
|||
|
TRUE,
|
|||
|
devAcl,
|
|||
|
FALSE
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Make a copy of the AFD descriptor. This copy will be the raw descriptor.
|
|||
|
//
|
|||
|
afdSecurityDescriptorLength = RtlLengthSecurityDescriptor(
|
|||
|
afdSecurityDescriptor
|
|||
|
);
|
|||
|
|
|||
|
localAfdAdminSecurityDescriptor = ExAllocatePoolWithTag (
|
|||
|
PagedPool,
|
|||
|
afdSecurityDescriptorLength,
|
|||
|
AFD_SECURITY_POOL_TAG
|
|||
|
);
|
|||
|
|
|||
|
if (localAfdAdminSecurityDescriptor == NULL) {
|
|||
|
KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_ERROR_LEVEL,
|
|||
|
"AFD: couldn't allocate security descriptor\n"));
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
|
|||
|
RtlMoveMemory(
|
|||
|
localAfdAdminSecurityDescriptor,
|
|||
|
afdSecurityDescriptor,
|
|||
|
afdSecurityDescriptorLength
|
|||
|
);
|
|||
|
|
|||
|
AfdAdminSecurityDescriptor = localAfdAdminSecurityDescriptor;
|
|||
|
|
|||
|
//
|
|||
|
// Now apply the local descriptor to the raw descriptor.
|
|||
|
//
|
|||
|
status = SeSetSecurityDescriptorInfo(
|
|||
|
NULL,
|
|||
|
&securityInformation,
|
|||
|
localSecurityDescriptor,
|
|||
|
&AfdAdminSecurityDescriptor,
|
|||
|
PagedPool,
|
|||
|
IoGetFileObjectGenericMapping()
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_ERROR_LEVEL,
|
|||
|
"AFD: SeSetSecurity failed, %lx\n",
|
|||
|
status));
|
|||
|
ASSERT (AfdAdminSecurityDescriptor==localAfdAdminSecurityDescriptor);
|
|||
|
ExFreePool (AfdAdminSecurityDescriptor);
|
|||
|
AfdAdminSecurityDescriptor = NULL;
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
|
|||
|
if (AfdAdminSecurityDescriptor!=localAfdAdminSecurityDescriptor) {
|
|||
|
ExFreePool (localAfdAdminSecurityDescriptor);
|
|||
|
}
|
|||
|
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
|
|||
|
error_exit:
|
|||
|
|
|||
|
ObReleaseObjectSecurity(
|
|||
|
afdSecurityDescriptor,
|
|||
|
memoryAllocated
|
|||
|
);
|
|||
|
|
|||
|
if (devAcl!=NULL) {
|
|||
|
AFD_FREE_POOL(
|
|||
|
devAcl,
|
|||
|
AFD_SECURITY_POOL_TAG
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
return(status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
AfdReadVolatileParameters (
|
|||
|
PVOID Parameter
|
|||
|
)
|
|||
|
{
|
|||
|
PAGED_CODE ();
|
|||
|
ExAcquireResourceExclusiveLite( AfdResource, TRUE );
|
|||
|
|
|||
|
if (AfdParametersNotifyHandle!=NULL) {
|
|||
|
ULONG i;
|
|||
|
NTSTATUS status;
|
|||
|
status = ZwNotifyChangeKey (
|
|||
|
AfdParametersNotifyHandle,
|
|||
|
NULL,
|
|||
|
(PIO_APC_ROUTINE)&AfdParametersNotifyWorker,
|
|||
|
(PVOID)(UINT_PTR)(unsigned int)DelayedWorkQueue,
|
|||
|
&AfdDontCareIoStatus,
|
|||
|
REG_NOTIFY_CHANGE_LAST_SET,
|
|||
|
FALSE,
|
|||
|
NULL, 0,
|
|||
|
TRUE);
|
|||
|
|
|||
|
if (NT_SUCCESS (status)) {
|
|||
|
for ( i = 0; i < AFD_VOLATILE_CONFIG_VAR_COUNT; i++ ) {
|
|||
|
|
|||
|
*AfdVolatileConfigInfo[i].Variable =
|
|||
|
AfdReadSingleParameter(
|
|||
|
AfdParametersNotifyHandle,
|
|||
|
AfdVolatileConfigInfo[i].RegistryValueName,
|
|||
|
*AfdVolatileConfigInfo[i].Variable
|
|||
|
);
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
DbgPrint (
|
|||
|
"AFD: Failed to start notification for volatile parameter changes, status: %lx\n",
|
|||
|
status);
|
|||
|
ZwClose (AfdParametersNotifyHandle);
|
|||
|
AfdParametersNotifyHandle = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
ASSERT (AfdParametersUnloadEvent!=NULL);
|
|||
|
IoQueueWorkItem (AfdWorkQueueItem,
|
|||
|
AfdReleaseRegistryHandleWait,
|
|||
|
DelayedWorkQueue,
|
|||
|
NULL);
|
|||
|
|
|||
|
}
|
|||
|
ExReleaseResourceLite( AfdResource );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
AfdReleaseRegistryHandleWait (
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN PVOID Context
|
|||
|
)
|
|||
|
{
|
|||
|
ASSERT (AfdParametersUnloadEvent!=NULL);
|
|||
|
KeSetEvent (AfdParametersUnloadEvent, AfdPriorityBoost, FALSE);
|
|||
|
}
|