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.
612 lines
14 KiB
612 lines
14 KiB
/*++
|
|
|
|
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_
|