Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

495 lines
11 KiB

/*++
Copyright (c) 1998-2001 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_
#ifdef __cplusplus
extern "C" {
#endif
//
// Kernel mode mappings to the user mode set defined in ulapi.h
//
//
// 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 contains a queue of HTTP_REQUEST objects
// CODEWORK: investigate using an NBQUEUE instead
//
typedef struct _UL_REQUEST_QUEUE
{
LONG RequestCount;
LONG MaxRequests;
LIST_ENTRY RequestHead;
} UL_REQUEST_QUEUE, *PUL_REQUEST_QUEUE;
//
// This structure represents an internal app pool object
//
#define IS_VALID_AP_OBJECT(pObject) \
(((pObject) != NULL) && ((pObject)->Signature == UL_APP_POOL_OBJECT_POOL_TAG) && ((pObject)->RefCount > 0))
typedef struct _UL_APP_POOL_OBJECT
{
//
// NonPagedPool
//
//
// lock that protects NewRequestQueue, 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 QueueSpinLock;
//
// 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;
//
// Locks lists on the app pool & process objects, is refcounted and
// given to the HTTP_REQUEST object to synchronize access to process
// objects when connections drop and the request(s) need to be released
//
PUL_NONPAGED_RESOURCE pResource;
//
// A apool wide new request list (when no irps are available)
//
UL_REQUEST_QUEUE NewRequestQueue;
//
// the demand start irp (OPTIONAL)
//
PIRP pDemandStartIrp;
PEPROCESS pDemandStartProcess;
//
// the list of processes bound to this app pool
//
LIST_ENTRY ProcessListHead;
PSECURITY_DESCRIPTOR pSecurityDescriptor;
//
// List of transient config groups
//
UL_NOTIFY_HEAD TransientHead;
//
// the length of pName
//
ULONG 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_ENABLED_STATE Enabled;
//
// 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) \
(((pObject) != NULL) && ((pObject)->Signature == UL_APP_POOL_PROCESS_POOL_TAG))
typedef struct _UL_APP_POOL_PROCESS
{
//
// NonPagedPool
//
//
// UL_APP_POOL_PROCESS_POOL_TAG
//
ULONG Signature;
//
// 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;
//
// lock that protects the above list
//
UL_SPIN_LOCK NewIrpSpinLock;
//
// 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
//
UL_REQUEST_QUEUE PendingRequestQueue;
//
// Pointer to the actual process (for debugging)
//
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 ULONG 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 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
FASTCALL
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
FASTCALL
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 \
)
// 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 OPTIONAL
);
// 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
);
VOID
UlUnlinkRequestFromProcess(
IN PUL_APP_POOL_OBJECT pAppPool,
IN PUL_INTERNAL_REQUEST pRequest
);
// IRQL == PASSIVE_LEVEL
//
NTSTATUS
UlGetPoolFromHandle(
IN HANDLE hAppPool,
OUT PUL_APP_POOL_OBJECT * ppAppPool
);
NTSTATUS
UlInitializeAP(
VOID
);
VOID
UlTerminateAP(
VOID
);
PUL_APP_POOL_PROCESS
UlCreateAppPoolProcess(
PUL_APP_POOL_OBJECT pObject
);
VOID
UlFreeAppPoolProcess(
PUL_APP_POOL_PROCESS pProcess
);
PUL_APP_POOL_OBJECT
UlAppPoolObjectFromProcess(
PUL_APP_POOL_PROCESS pProcess
);
VOID
UlLinkConfigGroupToAppPool(
IN PUL_CONFIG_GROUP_OBJECT pConfigGroup,
IN PUL_APP_POOL_OBJECT pAppPool
);
NTSTATUS
UlWaitForDisconnect(
IN PUL_APP_POOL_PROCESS pProcess,
IN PUL_HTTP_CONNECTION pHttpConn,
IN PIRP pIrp
);
VOID
UlCompleteAllWaitForDisconnect(
IN PUL_HTTP_CONNECTION pHttpConnection
);
NTSTATUS
UlpCopyRequestToBuffer(
IN PUL_INTERNAL_REQUEST pRequest,
IN PUCHAR pKernelBuffer,
IN PVOID pUserBuffer,
IN ULONG BufferLength,
IN PUCHAR pEntityBody,
IN ULONG EntityBodyLength
);
PUL_INTERNAL_REQUEST
UlpDequeueNewRequest(
IN PUL_APP_POOL_PROCESS pProcess
);
__inline
NTSTATUS
FASTCALL
UlpComputeRequestBytesNeeded(
IN PUL_INTERNAL_REQUEST pRequest,
IN PULONG pBytesNeeded
)
{
NTSTATUS Status;
ULONG SslInfoSize;
//
// 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.
//
// CODEWORK: Make this transport independent.
//
*pBytesNeeded += sizeof(HTTP_NETWORK_ADDRESS_IPV4) * 2;
//
// Include space for any SSL information.
//
if (pRequest->pHttpConn->SecureConnection)
{
Status = UlGetSslInfo(
&pRequest->pHttpConn->pConnection->FilterInfo,
0, // BufferSize
NULL, // pUserBuffer
NULL, // pBuffer
&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;
}
#ifdef __cplusplus
}; // extern "C"
#endif
#endif // _APOOL_H_