|
|
/*++
Copyright (c) 2000-2001 Microsoft Corporation
Module Name:
fastio.h
Abstract:
This module contains declarations related to fast I/O.
Author:
Chun Ye (chunye) 09-Dec-2000
Revision History:
--*/
#ifndef _FASTIO_H_
#define _FASTIO_H_
#ifdef __cplusplus
extern "C" { #endif
//
// Some useful macroes.
//
#define IS_LENGTH_SPECIFIED( pKnownHeaders ) \
(pKnownHeaders[HttpHeaderContentLength].RawValueLength > 0)
#define IS_CHUNK_SPECIFIED( pKnownHeaders ) \
(pKnownHeaders[HttpHeaderTransferEncoding].RawValueLength > 0 && \ 0 == _strnicmp( \ pKnownHeaders[HttpHeaderTransferEncoding].pRawValue, \ "chunked", \ strlen("chunked") \ )) \
//
// Inline functions to allocate/free a fast tracker.
//
__inline PUL_FULL_TRACKER FASTCALL UlpAllocateFastTracker( IN ULONG FixedHeaderLength, IN CCHAR SendIrpStackSize ) { PUL_FULL_TRACKER pTracker; ULONG SpaceLength; ULONG MaxFixedHeaderSize; USHORT MaxSendIrpSize; CCHAR MaxSendIrpStackSize;
//
// Sanity check.
//
PAGED_CODE();
if (FixedHeaderLength > g_UlMaxFixedHeaderSize || SendIrpStackSize > DEFAULT_MAX_IRP_STACK_SIZE) { MaxFixedHeaderSize = MAX(FixedHeaderLength, g_UlMaxFixedHeaderSize); MaxSendIrpStackSize = MAX(SendIrpStackSize, DEFAULT_MAX_IRP_STACK_SIZE); MaxSendIrpSize = (USHORT)ALIGN_UP(IoSizeOfIrp(MaxSendIrpStackSize), PVOID);
SpaceLength = ALIGN_UP(sizeof(UL_FULL_TRACKER), PVOID) + MaxSendIrpSize + MaxFixedHeaderSize + g_UlMaxVariableHeaderSize + g_UlMaxCopyThreshold + g_UlFixedHeadersMdlLength + g_UlVariableHeadersMdlLength + g_UlContentMdlLength;
pTracker = (PUL_FULL_TRACKER)UL_ALLOCATE_POOL( NonPagedPool, SpaceLength, UL_FULL_TRACKER_POOL_TAG );
if (pTracker) { pTracker->Signature = UL_FULL_TRACKER_POOL_TAG; pTracker->IrpContext.Signature = UL_IRP_CONTEXT_SIGNATURE; pTracker->IsFromLookaside = FALSE; pTracker->IsFromRequest = FALSE; pTracker->AuxilaryBufferLength = MaxFixedHeaderSize + g_UlMaxVariableHeaderSize + g_UlMaxCopyThreshold;
UlInitializeFullTrackerPool( pTracker, MaxSendIrpStackSize ); } } else { pTracker = UlPplAllocateFullTracker();
if (pTracker) { ASSERT(pTracker->Signature == MAKE_FREE_TAG(UL_FULL_TRACKER_POOL_TAG)); pTracker->Signature = UL_FULL_TRACKER_POOL_TAG; pTracker->pLogData = NULL;
// BUGBUG: I know we're trying to squeeze every last cycle
// out of the fast path, but can we really get away with
// this little initialization?
} }
return pTracker; } // UlpAllocateFastTracker
__inline VOID FASTCALL UlpFreeFastTracker( IN PUL_FULL_TRACKER pTracker ) { //
// Sanity check.
//
PAGED_CODE();
ASSERT( IS_VALID_FULL_TRACKER( pTracker ) );
if (pTracker->pLogData) { UlDestroyLogDataBuffer( pTracker->pLogData ); }
if (pTracker->IsFromRequest == FALSE) { if (pTracker->IsFromLookaside) { pTracker->Signature = MAKE_FREE_TAG(UL_FULL_TRACKER_POOL_TAG); UlPplFreeFullTracker( pTracker ); } else { UL_FREE_POOL_WITH_SIG( pTracker, UL_FULL_TRACKER_POOL_TAG ); } } } // UlpFreeFastTracker
//
// Dispatch routines for fast I/O.
//
extern FAST_IO_DISPATCH UlFastIoDispatch;
//
// Fast I/O routines.
//
BOOLEAN UlFastIoDeviceControl ( IN PFILE_OBJECT pFileObject, IN BOOLEAN Wait, IN PVOID pInputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID pOutputBuffer OPTIONAL, IN ULONG OutputBufferLength, IN ULONG IoControlCode, OUT PIO_STATUS_BLOCK pIoStatus, IN PDEVICE_OBJECT pDeviceObject );
BOOLEAN UlSendHttpResponseFastIo( IN PFILE_OBJECT pFileObject, IN BOOLEAN Wait, IN PVOID pInputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID pOutputBuffer OPTIONAL, IN ULONG OutputBufferLength, OUT PIO_STATUS_BLOCK pIoStatus, IN PDEVICE_OBJECT pDeviceObject, IN BOOLEAN RawResponse );
BOOLEAN UlReceiveHttpRequestFastIo( IN PFILE_OBJECT pFileObject, IN BOOLEAN Wait, IN PVOID pInputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID pOutputBuffer OPTIONAL, IN ULONG OutputBufferLength, OUT PIO_STATUS_BLOCK pIoStatus, IN PDEVICE_OBJECT pDeviceObject );
//
// Private prototypes.
//
NTSTATUS UlpFastSendHttpResponse( IN PHTTP_RESPONSE pUserResponse OPTIONAL, IN PHTTP_LOG_FIELDS_DATA pLogData OPTIONAL, IN PHTTP_DATA_CHUNK pDataChunk, IN ULONG ChunkCount, IN ULONG Flags, IN PUL_INTERNAL_REQUEST pRequest, IN PIRP pUserIrp OPTIONAL, OUT PULONG BytesSent );
VOID UlpRestartFastSendHttpResponse( IN PVOID pCompletionContext, IN NTSTATUS Status, IN ULONG_PTR Information );
VOID UlpFastSendCompleteWorker( IN PUL_WORK_ITEM pWorkItem );
NTSTATUS UlpFastReceiveHttpRequest( IN HTTP_REQUEST_ID RequestId, IN PUL_APP_POOL_PROCESS pProcess, IN PVOID pOutputBuffer, IN ULONG OutputBufferLength, OUT PULONG pBytesRead );
NTSTATUS UlpFastCopyHttpRequest( IN PUL_INTERNAL_REQUEST pRequest, IN PVOID pOutputBuffer, IN ULONG OutputBufferLength, OUT PULONG pBytesRead );
//
// An inline function to generate the content-length string.
//
__inline ULONG FASTCALL UlpFastGenerateContentLength( IN PCHAR LengthString, IN ULONG Length ) { ASSERT( ALIGN_UP_POINTER(LengthString, ULONG) == (PVOID)LengthString ); ASSERT( Length < 100000 );
if (Length >= 10000) { *((PULONG)LengthString) = *((PULONG)"0000"); LengthString[0] += (CHAR)((Length / 10000) % 10); LengthString[1] += (CHAR)((Length / 1000) % 10); LengthString[2] += (CHAR)((Length / 100) % 10); LengthString[3] += (CHAR)((Length / 10) % 10); LengthString[4] = (CHAR)('0' + (Length / 1) % 10); LengthString[5] = ANSI_NULL; return 5; } else if (Length >= 1000) { *((PULONG)LengthString) = *((PULONG)"0000"); LengthString[0] += (CHAR)((Length / 1000) % 10); LengthString[1] += (CHAR)((Length / 100) % 10); LengthString[2] += (CHAR)((Length / 10) % 10); LengthString[3] += (CHAR)((Length / 1) % 10); LengthString[4] = ANSI_NULL; return 4; } else if (Length >= 100) { *((PULONG)LengthString) = *((PULONG)"0000"); LengthString[0] += (CHAR)((Length / 100) % 10); LengthString[1] += (CHAR)((Length / 10) % 10); LengthString[2] += (CHAR)((Length / 1) % 10); LengthString[3] = ANSI_NULL; return 3; } else if (Length >= 10) { *((PUSHORT)LengthString) = *((PUSHORT)"00"); LengthString[0] += (CHAR)((Length / 10) % 10); LengthString[1] += (CHAR)((Length / 1) % 10); LengthString[2] = ANSI_NULL; return 2; } else { LengthString[0] = (CHAR)('0' + (Length / 1) % 10); LengthString[1] = ANSI_NULL; return 1; } } // UlpFastGenerateContentLength
//
// An inline function to ProbeForRead the header portions of the HTTP_RESPONSE.
//
#define UL_MAX_HTTP_STATUS_CODE 999
__inline NTSTATUS FASTCALL UlProbeHttpHeaders( IN PHTTP_RESPONSE pUserResponse ) { NTSTATUS Status; PHTTP_UNKNOWN_HEADER pUnknownHeaders; USHORT Length; LONG i;
Status = STATUS_SUCCESS;
if (pUserResponse == NULL) { return Status; }
__try { //
// Check flags and status code.
//
if ((pUserResponse->Flags & ~HTTP_RESPONSE_FLAG_VALID) || (pUserResponse->StatusCode > UL_MAX_HTTP_STATUS_CODE)) { ExRaiseStatus( STATUS_INVALID_PARAMETER ); }
//
// Check the response structure.
//
ProbeTestForRead( pUserResponse, sizeof(HTTP_RESPONSE), sizeof(USHORT) );
//
// Check the reason string.
//
ProbeTestForRead( pUserResponse->pReason, pUserResponse->ReasonLength, sizeof(CHAR) );
//
// Loop through the known headers.
//
for (i = 0; i < HttpHeaderResponseMaximum; i++) { Length = pUserResponse->Headers.pKnownHeaders[i].RawValueLength;
if (Length > 0) { ProbeTestForRead( pUserResponse->Headers.pKnownHeaders[i].pRawValue, Length, sizeof(CHAR) ); } }
//
// And the unknown headers (this might throw an exception).
//
pUnknownHeaders = pUserResponse->Headers.pUnknownHeaders;
if (pUnknownHeaders != NULL) { ProbeTestForRead( pUnknownHeaders, sizeof(HTTP_UNKNOWN_HEADER) * pUserResponse->Headers.UnknownHeaderCount, sizeof(ULONG) );
for (i = 0; i < (LONG)(pUserResponse->Headers.UnknownHeaderCount); i++) { if (pUnknownHeaders[i].NameLength > 0) { ProbeTestForRead( pUnknownHeaders[i].pName, pUnknownHeaders[i].NameLength, sizeof(CHAR) );
ProbeTestForRead( pUnknownHeaders[i].pRawValue, pUnknownHeaders[i].RawValueLength, sizeof(CHAR) ); } } }
UlTrace(IOCTL, ("UlProbeHttpHeaders validated the headers: %x\n", Status)); } __except( UL_EXCEPTION_FILTER() ) { Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode()); UlTrace(IOCTL, ("UlProbeHttpHeaders caught an exception: %x\n", Status)); }
return Status; } // UlProbeHttpHeaders
#ifdef __cplusplus
}; // extern "C"
#endif
#endif // _FASTIO_H_
|