|
|
/*++
Copyright (c) 1999-2000 Microsoft Corporation
Module Name:
cgi_handler.h
Abstract:
Handler class for CGI
Author:
Taylor Weiss (TaylorW) 01-Feb-1999
Revision History:
--*/
#ifndef _CGI_HANDLER_H_
#define _CGI_HANDLER_H_
#define MAX_CGI_BUFFERING 2048
enum CGI_STATE { CgiStateStart, CgiStateProcessingRequestEntity, CgiStateProcessingResponseHeaders, CgiStateProcessingResponseEntity, CgiStateDoneWithRequest };
class W3_CGI_HANDLER : public W3_HANDLER { public: W3_CGI_HANDLER( W3_CONTEXT * pW3Context, META_SCRIPT_MAP_ENTRY * pScriptMapEntry, LPSTR pszSSICommandLine = NULL ) : W3_HANDLER (pW3Context, pScriptMapEntry), m_cbData (0), m_hStdOut (INVALID_HANDLE_VALUE), m_hStdIn (INVALID_HANDLE_VALUE), m_hProcess (NULL), m_hTimer (NULL), m_dwRequestState (CgiStateStart), m_fResponseRedirected (FALSE), m_bytesToSend (INFINITE), m_bytesToReceive (0), m_fEntityBodyPreloadComplete (FALSE), m_pszSSICommandLine(pszSSICommandLine), m_fIsNphCgi (FALSE) { ZeroMemory(&m_Overlapped, sizeof OVERLAPPED);
InitializeListHead(&m_CgiListEntry);
EnterCriticalSection(&sm_CgiListLock); InsertHeadList(&sm_CgiListHead, &m_CgiListEntry); LeaveCriticalSection(&sm_CgiListLock);
// perf ctr
pW3Context->QuerySite()->IncCgiReqs();
if ( ETW_IS_TRACE_ON(ETW_LEVEL_CP) ) { HTTP_REQUEST_ID RequestId = pW3Context->QueryRequest()->QueryRequestId();
g_pEtwTracer->EtwTraceEvent( &CgiEventGuid, ETW_TYPE_START, &RequestId, sizeof(HTTP_REQUEST_ID), NULL, 0 ); }
if (pszSSICommandLine != NULL) { m_fIsNphCgi = TRUE; } }
~W3_CGI_HANDLER();
WCHAR *QueryName() { return L"CGIHandler"; }
CONTEXT_STATUS DoWork();
CONTEXT_STATUS OnCompletion(IN DWORD cbCompletion, IN DWORD dwCompletionStatus);
static HRESULT Initialize();
static VOID KillAllCgis();
static VOID Terminate();
private:
HRESULT CGIStartProcessing();
HRESULT CGIContinueOnClientCompletion();
HRESULT CGIContinueOnPipeCompletion(BOOL *pfIsCgiError);
HRESULT CGIReadRequestEntity(BOOL *pfIoPending);
HRESULT CGIWriteResponseEntity();
HRESULT CGIReadCGIOutput();
HRESULT CGIWriteCGIInput();
HRESULT ProcessCGIOutput();
HRESULT SetupChildEnv(OUT BUFFER *pBuffer);
static HRESULT SetupChildPipes(OUT HANDLE *phStdOut, OUT HANDLE *phStdIn, IN OUT STARTUPINFO *pstartupinfo);
static VOID CALLBACK CGITerminateProcess(PVOID pContext, BOOLEAN);
BOOL QueryIsNphCgi() const { return m_fIsNphCgi; }
static VOID CALLBACK OnPipeIoCompletion( DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped);
static BOOL sm_fForwardServerEnvironmentBlock; static WCHAR * sm_pEnvString; static DWORD sm_cchEnvLength; static LIST_ENTRY sm_CgiListHead; static CRITICAL_SECTION sm_CgiListLock;
//
// DWORD containing the state of the current request
//
CGI_STATE m_dwRequestState; BOOL m_fResponseRedirected;
//
// The timer callback handle
//
HANDLE m_hTimer;
//
// Parent's input and output handles and child's process handle
//
HANDLE m_hStdOut; HANDLE m_hStdIn; HANDLE m_hProcess;
//
// Variable to keep track of how many more bytes of request/response left
//
DWORD m_bytesToSend; DWORD m_bytesToReceive;
//
// Buffer to do I/O to/from CGI/client
//
CHAR m_DataBuffer[MAX_CGI_BUFFERING];
//
// Buffer to store response headers
//
BUFFER m_bufResponseHeaders;
//
// Number of bytes in the buffer (m_DataBuffer or
// m_bufResponseHeaders) currently
//
DWORD m_cbData;
//
// OVERLAPPED structure for async I/O
//
OVERLAPPED m_Overlapped;
//
// Store a list of active CGI requests so we can timeout bad requests
//
LIST_ENTRY m_CgiListEntry;
//
// Have we completed preloading the entity body
//
BOOL m_fEntityBodyPreloadComplete;
//
// For the SSI #EXEC CMD case, m_pszSSICommandLine contains the explicit
// command to execute
//
// Note: CGI_HANDLER does not own this string so it doesn't need to
// free it.
//
LPSTR m_pszSSICommandLine;
//
// Is this an nph CGI (or a cmd exec from SSI)
//
BOOL m_fIsNphCgi; };
//
// This is the exit code given to processes that we terminate
//
#define CGI_PREMATURE_DEATH_CODE 0xf1256323
#endif // _CGI_HANDLER_H_
|