/*++ 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_