|
|
/*++
Copyright (c) 1998-2002 Microsoft Corporation
Module Name:
apool.h
Abstract:
The public definition of app pool interfaces.
Author:
Paul McDaniel (paulmcd) 28-Jan-1999
Revision History:
--*/
#ifndef _APOOL_H_
#define _APOOL_H_
//
// Kernel mode mappings to the user mode set defined in ulapi.h
//
//
// Constants.
//
#define UL_MAX_APP_POOL_NAME_SIZE (MAX_PATH*sizeof(WCHAR))
#define UL_MAX_REQUESTS_QUEUED 0xFFFF
#define UL_MIN_REQUESTS_QUEUED 10
//
// Forwarders.
//
typedef struct _UL_INTERNAL_REQUEST *PUL_INTERNAL_REQUEST; typedef struct _UL_HTTP_CONNECTION *PUL_HTTP_CONNECTION; typedef struct _UL_CONFIG_GROUP_OBJECT *PUL_CONFIG_GROUP_OBJECT;
//
// This structure represents an internal app pool object
//
#define IS_VALID_AP_OBJECT(pObject) \
(HAS_VALID_SIGNATURE(pObject, UL_APP_POOL_OBJECT_POOL_TAG) \ && ((pObject)->RefCount > 0))
typedef struct _UL_APP_POOL_OBJECT { //
// NonPagedPool
//
//
// Lock that protects NewRequestQueue and PendingRequestQueue
// for each attached process and queue state of the request
//
// ensure it on cache-line and use InStackQueuedSpinLock for
// better performance
//
UL_SPIN_LOCK SpinLock;
//
// UL_APP_POOL_OBJECT_POOL_TAG
//
ULONG Signature;
//
// Ref count for this app pool
//
LONG RefCount;
//
// links all apool objects, anchored by g_AppPoolListHead
//
LIST_ENTRY ListEntry;
//
// A apool wide new request list (when no irps are available)
//
LIST_ENTRY NewRequestHead; ULONG RequestCount; ULONG MaxRequests;
//
// the demand start irp (OPTIONAL)
//
PIRP pDemandStartIrp; PEPROCESS pDemandStartProcess;
//
// the control channel associated with this app pool
//
PUL_CONTROL_CHANNEL pControlChannel;
//
// the list of processes bound to this app pool
//
LIST_ENTRY ProcessListHead;
PSECURITY_DESCRIPTOR pSecurityDescriptor;
//
// the length of pName
//
USHORT NameLength;
//
// number of active processes in the AppPool, used to decide if binding
// is necessary
//
ULONG NumberActiveProcesses;
//
// Only route requests to this AppPool if it's marked active
//
HTTP_APP_POOL_ENABLED_STATE State;
//
// How sophisticated is the load balancer routing requests to the apppool?
//
HTTP_LOAD_BALANCER_CAPABILITIES LoadBalancerCapability;
//
// the apool's name
//
WCHAR pName[0];
} UL_APP_POOL_OBJECT, *PUL_APP_POOL_OBJECT;
//
// The structure representing a process bound to an app pool.
//
#define IS_VALID_AP_PROCESS(pObject) \
HAS_VALID_SIGNATURE(pObject, UL_APP_POOL_PROCESS_POOL_TAG)
typedef struct _UL_APP_POOL_PROCESS { //
// NonPagedPool
//
//
// UL_APP_POOL_PROCESS_POOL_TAG
//
ULONG Signature;
//
// Ref count for this app pool process. This is more like an outstanding
// io count rather than the refcount. The process is still get cleaned
// with ULClose call. But completion for the cleanup delays until all
// send io exhaust on the process.
//
LONG RefCount;
//
// CleanUpIrp will be completed when all the IO exhaust on
// the cleanup pending process.
//
PIRP pCleanupIrp;
//
// set if we are in cleanup. You must check this flag before attaching
// any IRPs to the process.
//
ULONG InCleanup : 1;
//
// set if process is attached with the HTTP_OPTION_CONTROLLER option
//
ULONG Controller : 1;
//
// used to link into the apool object
//
LIST_ENTRY ListEntry;
//
// points to the app pool this process belongs
//
PUL_APP_POOL_OBJECT pAppPool;
//
// a list of pending IRP(s) waiting to receive new requests
//
LIST_ENTRY NewIrpHead;
//
// links requests that would not fit in a irp buffer and need to wait for
// the larger buffer
//
// and
//
// requests that this process is working on and need
// i/o cancellation if the process detaches from the apool
//
LIST_ENTRY PendingRequestHead;
//
// Pointer to the actual process.
//
PEPROCESS pProcess;
//
// List of pending "wait for disconnect" IRPs.
//
UL_NOTIFY_HEAD WaitForDisconnectHead;
} UL_APP_POOL_PROCESS, *PUL_APP_POOL_PROCESS;
// IRQL == PASSIVE_LEVEL
//
NTSTATUS UlAttachProcessToAppPool( IN PWCHAR pName OPTIONAL, IN USHORT NameLength, IN BOOLEAN Create, IN PACCESS_STATE pAccessState, IN ACCESS_MASK DesiredAccess, IN KPROCESSOR_MODE RequestorMode, OUT PUL_APP_POOL_PROCESS * ppProcess );
// IRQL == PASSIVE_LEVEL
//
NTSTATUS UlDetachProcessFromAppPool( IN PIRP pCleanupIrp, IN PIO_STACK_LOCATION pCleanupIrpSp );
VOID UlShutdownAppPoolProcess( IN PUL_APP_POOL_PROCESS pProcess );
// IRQL == PASSIVE_LEVEL
//
#if REFERENCE_DEBUG
VOID UlReferenceAppPool( IN PUL_APP_POOL_OBJECT pAppPool REFERENCE_DEBUG_FORMAL_PARAMS ); #else
__inline VOID UlReferenceAppPool( IN PUL_APP_POOL_OBJECT pAppPool ) { InterlockedIncrement(&pAppPool->RefCount); } #endif
#define REFERENCE_APP_POOL( papp ) \
UlReferenceAppPool( \ (papp) \ REFERENCE_DEBUG_ACTUAL_PARAMS \ )
// IRQL == PASSIVE_LEVEL
//
VOID UlDeleteAppPool( IN PUL_APP_POOL_OBJECT pAppPool REFERENCE_DEBUG_FORMAL_PARAMS );
#define DELETE_APP_POOL( papp ) \
UlDeleteAppPool( \ (papp) \ REFERENCE_DEBUG_ACTUAL_PARAMS \ )
#if REFERENCE_DEBUG
VOID UlDereferenceAppPool( IN PUL_APP_POOL_OBJECT pAppPool REFERENCE_DEBUG_FORMAL_PARAMS ); #else
__inline VOID UlDereferenceAppPool( IN PUL_APP_POOL_OBJECT pAppPool ) { if (InterlockedDecrement(&pAppPool->RefCount) == 0) { UlDeleteAppPool(pAppPool); } } #endif
#define DEREFERENCE_APP_POOL( papp ) \
UlDereferenceAppPool( \ (papp) \ REFERENCE_DEBUG_ACTUAL_PARAMS \ )
VOID UlpCleanUpAppoolProcess( IN PUL_APP_POOL_PROCESS pAppPoolProcess );
#if REFERENCE_DEBUG
VOID UlReferenceAppPoolProcess( IN PUL_APP_POOL_PROCESS pAppPoolProcess REFERENCE_DEBUG_FORMAL_PARAMS );
VOID UlDereferenceAppPoolProcess( IN PUL_APP_POOL_PROCESS pAppPoolProcess REFERENCE_DEBUG_FORMAL_PARAMS );
#else
__inline VOID UlReferenceAppPoolProcess( IN PUL_APP_POOL_PROCESS pAppPoolProcess ) { InterlockedIncrement(&pAppPoolProcess->RefCount); }
__inline VOID UlDereferenceAppPoolProcess( IN PUL_APP_POOL_PROCESS pAppPoolProcess ) { if (InterlockedDecrement(&pAppPoolProcess->RefCount) == 0) { UlpCleanUpAppoolProcess(pAppPoolProcess); } } #endif
#define REFERENCE_APP_POOL_PROCESS( papp ) \
UlReferenceAppPoolProcess( \ (papp) \ REFERENCE_DEBUG_ACTUAL_PARAMS \ ) #define DEREFERENCE_APP_POOL_PROCESS( papp ) \
UlDereferenceAppPoolProcess( \ (papp) \ REFERENCE_DEBUG_ACTUAL_PARAMS \ )
// IRQL == PASSIVE_LEVEL
//
NTSTATUS UlQueryAppPoolInformation( IN PUL_APP_POOL_PROCESS pProcess, IN HTTP_APP_POOL_INFORMATION_CLASS InformationClass, OUT PVOID pAppPoolInformation, IN ULONG Length, OUT PULONG pReturnLength );
// IRQL == PASSIVE_LEVEL
//
NTSTATUS UlSetAppPoolInformation( IN PUL_APP_POOL_PROCESS pProcess, IN HTTP_APP_POOL_INFORMATION_CLASS InformationClass, IN PVOID pAppPoolInformation, IN ULONG Length );
// IRQL == PASSIVE_LEVEL
//
NTSTATUS UlWaitForDemandStart( IN PUL_APP_POOL_PROCESS pProcess, IN PIRP pIrp );
// IRQL == PASSIVE_LEVEL
//
NTSTATUS UlReceiveHttpRequest( IN HTTP_REQUEST_ID RequestId, IN ULONG Flags, IN PUL_APP_POOL_PROCESS pProcess, IN PIRP pIrp );
// IRQL == PASSIVE_LEVEL
//
NTSTATUS UlDeliverRequestToProcess( IN PUL_APP_POOL_OBJECT pAppPool, IN PUL_INTERNAL_REQUEST pRequest, OUT PIRP *pIrpToComplete OPTIONAL );
/***************************************************************************++
Routine Description:
Gets the current app pool queue state of the request.
Arguments:
pProcess - Request object return value - The current appool queue state of the request
--***************************************************************************/ __inline BOOLEAN UlCheckAppPoolState( IN PUL_INTERNAL_REQUEST pRequest ) { PUL_APP_POOL_PROCESS pProcess;
//
// Check the AppPool queue state of the request.
//
if (QueueCopiedState != pRequest->AppPool.QueueState) { return FALSE; }
//
// Check if the process has been detached. Since we never unset
// pRequest->AppPool.pProcess until the reference of the request
// drops to 0, it is safe to use pProcess this way here.
//
pProcess = pRequest->AppPool.pProcess; ASSERT(!pProcess || IS_VALID_AP_PROCESS(pProcess));
if (!pProcess || pProcess->InCleanup) { return FALSE; }
return TRUE; }
VOID UlUnlinkRequestFromProcess( IN PUL_APP_POOL_OBJECT pAppPool, IN PUL_INTERNAL_REQUEST pRequest );
// IRQL == PASSIVE_LEVEL
//
NTSTATUS UlGetPoolFromHandle( IN HANDLE hAppPool, IN KPROCESSOR_MODE AccessMode, OUT PUL_APP_POOL_OBJECT * ppAppPool );
NTSTATUS UlInitializeAP( VOID );
VOID UlTerminateAP( VOID );
PUL_APP_POOL_PROCESS UlCreateAppPoolProcess( PUL_APP_POOL_OBJECT pObject );
VOID UlCloseAppPoolProcess( PUL_APP_POOL_PROCESS pProcess );
NTSTATUS UlWaitForDisconnect( IN PUL_APP_POOL_PROCESS pProcess, IN PUL_HTTP_CONNECTION pHttpConn, IN PIRP pIrp );
VOID UlCompleteAllWaitForDisconnect( IN PUL_HTTP_CONNECTION pHttpConnection );
VOID UlCopyRequestToIrp( IN PUL_INTERNAL_REQUEST pRequest, IN PIRP pIrp, IN BOOLEAN CompleteIrp, IN BOOLEAN LockAcquired );
NTSTATUS UlCopyRequestToBuffer( IN PUL_INTERNAL_REQUEST pRequest, IN PUCHAR pKernelBuffer, IN PVOID pUserBuffer, IN ULONG BufferLength, IN ULONG Flags, IN BOOLEAN LockAcquired, OUT PULONG pBytesCopied );
NTSTATUS UlDequeueNewRequest( IN PUL_APP_POOL_PROCESS pProcess, IN ULONG RequestBufferLength, OUT PUL_INTERNAL_REQUEST * pRequest );
VOID UlRequeuePendingRequest( IN PUL_APP_POOL_PROCESS pProcess, IN PUL_INTERNAL_REQUEST pRequest );
__inline NTSTATUS UlComputeRequestBytesNeeded( IN PUL_INTERNAL_REQUEST pRequest, IN PULONG pBytesNeeded ) { NTSTATUS Status; ULONG SslInfoSize;
C_ASSERT(SOCKADDR_ADDRESS_LENGTH_IP6 >= SOCKADDR_ADDRESS_LENGTH_IP);
//
// Calculate the size needed for the request, we'll need it below.
//
*pBytesNeeded = sizeof(HTTP_REQUEST) + pRequest->TotalRequestSize + (pRequest->UnknownHeaderCount * sizeof(HTTP_UNKNOWN_HEADER));
//
// Include additional space for the local and remote addresses.
//
*pBytesNeeded += 2 * ALIGN_UP(SOCKADDR_ADDRESS_LENGTH_IP6, PVOID);
//
// Include space for any SSL information.
//
if (pRequest->pHttpConn->SecureConnection) { Status = UlGetSslInfo( &pRequest->pHttpConn->pConnection->FilterInfo, 0, // BufferSize
NULL, // pUserBuffer
NULL, // pProcess (WP)
NULL, // pBuffer
NULL, // pMappedToken
&SslInfoSize // pBytesNeeded
);
if (NT_SUCCESS(Status)) { //
// Struct must be aligned; add some slop space
//
*pBytesNeeded = ALIGN_UP(*pBytesNeeded, PVOID); *pBytesNeeded += SslInfoSize; } else { return Status; } }
return STATUS_SUCCESS;
} // UlComputeRequestBytesNeeded
#endif // _APOOL_H_
|