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.
706 lines
20 KiB
706 lines
20 KiB
/******************************************************************************
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
HttpContext.cpp
|
|
|
|
Abstract:
|
|
This file contains the implementation of the MPCHttpContext class,
|
|
which handles the interface with IIS.
|
|
|
|
Revision History:
|
|
Davide Massarenti (Dmassare) 04/20/99
|
|
created
|
|
|
|
******************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
|
#define BUFFER_SIZE_TMP (64)
|
|
|
|
|
|
static const char szStatus [] = "200 OK";
|
|
static const char szNewLine[] = "\r\n";
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Static functions.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
static void SupportAddHeader( /*[in/out]*/ MPC::string& szHeaders ,
|
|
/*[in] */ const char* szHeaderName ,
|
|
/*[in] */ const char* szHeaderValue )
|
|
{
|
|
__ULT_FUNC_ENTRY("SupportAddHeader");
|
|
|
|
|
|
szHeaders.append( szHeaderName );
|
|
szHeaders.append( ": " );
|
|
szHeaders.append( szHeaderValue );
|
|
szHeaders.append( szNewLine );
|
|
}
|
|
|
|
static void SupportAddHeader( /*[in/out]*/ MPC::string& szHeaders ,
|
|
/*[in] */ const char* szHeaderName ,
|
|
/*[in] */ DWORD dwHeaderValue )
|
|
{
|
|
__ULT_FUNC_ENTRY("SupportAddHeader");
|
|
|
|
char rgBuf[BUFFER_SIZE_TMP];
|
|
|
|
|
|
sprintf( rgBuf, "%lu", dwHeaderValue );
|
|
|
|
SupportAddHeader( szHeaders, szHeaderName, rgBuf );
|
|
}
|
|
|
|
static void SupportEndHeaders( /*[in/out]*/ MPC::string& szHeaders )
|
|
{
|
|
__ULT_FUNC_ENTRY("SupportEndHeaders");
|
|
|
|
|
|
szHeaders.append( szNewLine );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Construction/Destruction
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
MPCHttpContext::MPCHttpContext() : m_hsInput (g_Heap),
|
|
m_hsOutput(g_Heap)
|
|
{
|
|
__ULT_FUNC_ENTRY("MPCHttpContext::MPCHttpContext");
|
|
|
|
|
|
m_pECB = NULL;
|
|
|
|
m_mpcsServer = NULL;
|
|
m_dwSkippedInput = 0;
|
|
m_fRequestProcessed = FALSE;
|
|
m_fKeepConnection = TRUE;
|
|
|
|
m_fAsync = FALSE;
|
|
m_FSMstate = FSM_REGISTER;
|
|
m_IOstate = IO_IDLE;
|
|
|
|
|
|
#ifdef DEBUG
|
|
m_Debug_NO_RESPONSE_TO_OPEN = false;
|
|
|
|
m_Debug_NO_RESPONSE_TO_WRITE = false;
|
|
|
|
m_Debug_RESPONSE_TO_OPEN = false;
|
|
m_Debug_RESPONSE_TO_OPEN_response = 0;
|
|
m_Debug_RESPONSE_TO_OPEN_position = -1;
|
|
m_Debug_RESPONSE_TO_OPEN_protocol = UPLOAD_LIBRARY_PROTOCOL_VERSION_SRV;
|
|
|
|
m_Debug_RESPONSE_TO_WRITE = false;
|
|
m_Debug_RESPONSE_TO_WRITE_response = 0;
|
|
m_Debug_RESPONSE_TO_WRITE_position = -1;
|
|
m_Debug_RESPONSE_TO_WRITE_protocol = UPLOAD_LIBRARY_PROTOCOL_VERSION_SRV;
|
|
|
|
m_Debug_RANDOM_POINTER_ERROR = false;
|
|
m_Debug_RANDOM_POINTER_ERROR_pos_low = 0;
|
|
m_Debug_RANDOM_POINTER_ERROR_pos_high = -1;
|
|
|
|
m_Debug_FIXED_POINTER_ERROR = false;
|
|
m_Debug_FIXED_POINTER_ERROR_pos = 0;
|
|
#endif
|
|
}
|
|
|
|
MPCHttpContext::~MPCHttpContext()
|
|
{
|
|
__ULT_FUNC_ENTRY("MPCHttpContext::~MPCHttpContext");
|
|
|
|
|
|
if(m_mpcsServer) delete m_mpcsServer;
|
|
|
|
if(m_fAsync && m_pECB)
|
|
{
|
|
//
|
|
// Close session.
|
|
//
|
|
m_pECB->ServerSupportFunction( m_pECB->ConnID ,
|
|
HSE_REQ_DONE_WITH_SESSION ,
|
|
NULL ,
|
|
NULL ,
|
|
NULL );
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Callbacks
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
VOID WINAPI MPCHttpContext::IOCompletion( /*[in]*/ EXTENSION_CONTROL_BLOCK* pECB ,
|
|
/*[in]*/ PVOID pContext ,
|
|
/*[in]*/ DWORD cbIO ,
|
|
/*[in]*/ DWORD dwError )
|
|
{
|
|
__ULT_FUNC_ENTRY("MPCHttpContext::IOCompletion");
|
|
|
|
MPCHttpContext* ptr = NULL;
|
|
|
|
try
|
|
{
|
|
ptr = reinterpret_cast<MPCHttpContext*>(pContext);
|
|
|
|
ptr->m_pECB = pECB;
|
|
|
|
if(dwError != ERROR_SUCCESS)
|
|
{
|
|
delete ptr; ptr = NULL;
|
|
}
|
|
else
|
|
{
|
|
switch( ptr->m_IOstate )
|
|
{
|
|
case IO_IDLE:
|
|
break;
|
|
|
|
case IO_READING:
|
|
//
|
|
// If the request has already been processed, simply count the number of bytes received.
|
|
//
|
|
if(ptr->m_fRequestProcessed)
|
|
{
|
|
ptr->m_dwSkippedInput += cbIO;
|
|
}
|
|
else
|
|
{
|
|
ptr->m_hsInput.write( ptr->m_rgBuffer, cbIO );
|
|
}
|
|
|
|
//
|
|
// If this is the last request (cbIO==0) or the number of bytes skipped is equal to the number of missing bytes,
|
|
// proceed to the next phase.
|
|
//
|
|
if(cbIO == 0 || ptr->m_dwSkippedInput == ptr->m_hsInput.GetAvailableForWrite())
|
|
{
|
|
ptr->m_IOstate = IO_IDLE;
|
|
}
|
|
else
|
|
{
|
|
if(ptr->Fsm_Process() == HSE_STATUS_ERROR)
|
|
{
|
|
delete ptr; ptr = NULL;
|
|
}
|
|
else
|
|
{
|
|
ptr->AsyncRead();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IO_WRITING:
|
|
if(cbIO == 0 || ptr->m_hsOutput.IsEOR())
|
|
{
|
|
ptr->m_IOstate = IO_IDLE;
|
|
}
|
|
else
|
|
{
|
|
ptr->AsyncWrite();
|
|
}
|
|
break;
|
|
}
|
|
|
|
if(ptr->m_IOstate == IO_IDLE)
|
|
{
|
|
ptr->AdvanceFSM();
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
__ULT_TRACE_ERROR( UPLOADLIBID, "Upload Server raised an exception. Gracefully exiting..." );
|
|
|
|
(void)g_NTEvents.LogEvent( EVENTLOG_ERROR_TYPE, PCHUL_ERR_EXCEPTION,
|
|
L"" , // %1 = SERVER
|
|
L"IOCompletion", // %2 = CLIENT
|
|
NULL );
|
|
|
|
if(ptr)
|
|
{
|
|
delete ptr; ptr = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Protected Methods.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
DWORD MPCHttpContext::AsyncRead()
|
|
{
|
|
__ULT_FUNC_ENTRY("MPCHttpContext::AsyncRead");
|
|
|
|
DWORD dwRes = HSE_STATUS_SUCCESS;
|
|
DWORD dwSize = m_hsInput.GetAvailableForWrite();
|
|
|
|
|
|
//
|
|
// If not all the data has been read, ask for async I/O operation.
|
|
//
|
|
if(dwSize)
|
|
{
|
|
DWORD dwTmp = HSE_IO_ASYNC;
|
|
|
|
m_fAsync = TRUE;
|
|
m_IOstate = IO_READING;
|
|
|
|
dwSize = min( dwSize, sizeof(m_rgBuffer) );
|
|
|
|
if(!m_pECB->ServerSupportFunction( m_pECB->ConnID ,
|
|
HSE_REQ_ASYNC_READ_CLIENT,
|
|
m_rgBuffer ,
|
|
&dwSize ,
|
|
&dwTmp ))
|
|
{
|
|
dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE;
|
|
}
|
|
else
|
|
{
|
|
dwRes = HSE_STATUS_PENDING; __ULT_FUNC_LEAVE;
|
|
}
|
|
}
|
|
|
|
|
|
__ULT_FUNC_CLEANUP;
|
|
|
|
__ULT_FUNC_EXIT(dwRes);
|
|
}
|
|
|
|
DWORD MPCHttpContext::AsyncWrite()
|
|
{
|
|
__ULT_FUNC_ENTRY("MPCHttpContext::AsyncWrite");
|
|
|
|
DWORD dwRes = HSE_STATUS_SUCCESS;
|
|
DWORD dwSize = m_hsOutput.GetAvailableForRead();
|
|
|
|
|
|
//
|
|
// If not all the data has been read, ask for async I/O operation.
|
|
//
|
|
if(dwSize)
|
|
{
|
|
m_fAsync = TRUE;
|
|
m_IOstate = IO_WRITING;
|
|
|
|
dwSize = min( dwSize, sizeof(m_rgBuffer) );
|
|
|
|
if(FAILED(m_hsOutput.read( m_rgBuffer, dwSize )))
|
|
{
|
|
dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE;
|
|
}
|
|
|
|
if(m_pECB->WriteClient( m_pECB->ConnID, m_rgBuffer, &dwSize, HSE_IO_ASYNC ) == FALSE)
|
|
{
|
|
dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE;
|
|
}
|
|
|
|
dwRes = HSE_STATUS_PENDING; __ULT_FUNC_LEAVE;
|
|
}
|
|
|
|
|
|
__ULT_FUNC_CLEANUP;
|
|
|
|
__ULT_FUNC_EXIT(dwRes);
|
|
}
|
|
|
|
|
|
DWORD MPCHttpContext::AdvanceFSM()
|
|
{
|
|
__ULT_FUNC_ENTRY("MPCHttpContext::AdvanceFSM");
|
|
|
|
DWORD dwRes = HSE_STATUS_SUCCESS;
|
|
bool fClean = false;
|
|
|
|
|
|
while(dwRes == HSE_STATUS_SUCCESS)
|
|
{
|
|
switch(m_FSMstate)
|
|
{
|
|
case FSM_REGISTER: m_FSMstate = FSM_INPUT ; dwRes = Fsm_Register (); break; // Register IO callback.
|
|
case FSM_INPUT : m_FSMstate = FSM_PROCESS; dwRes = Fsm_ReceiveInput(); break; // Read all the input.
|
|
case FSM_PROCESS : m_FSMstate = FSM_OUTPUT ; dwRes = Fsm_Process (); break; // Process request.
|
|
case FSM_OUTPUT : m_FSMstate = FSM_DELETE ; dwRes = Fsm_SendOutput (); break; // Send output.
|
|
case FSM_DELETE : fClean = true; __ULT_FUNC_LEAVE; // Delete the request object.
|
|
}
|
|
}
|
|
|
|
if(dwRes != HSE_STATUS_SUCCESS &&
|
|
dwRes != HSE_STATUS_PENDING )
|
|
{
|
|
fClean = true;
|
|
}
|
|
|
|
|
|
__ULT_FUNC_CLEANUP;
|
|
|
|
if(fClean) delete this;
|
|
|
|
__ULT_FUNC_EXIT(dwRes);
|
|
}
|
|
|
|
|
|
DWORD MPCHttpContext::Fsm_Register()
|
|
{
|
|
__ULT_FUNC_ENTRY("MPCHttpContext::Fsm_Register");
|
|
|
|
DWORD dwRes = HSE_STATUS_SUCCESS;
|
|
|
|
|
|
if(!m_pECB->ServerSupportFunction( m_pECB->ConnID ,
|
|
HSE_REQ_IO_COMPLETION,
|
|
IOCompletion ,
|
|
NULL ,
|
|
(LPDWORD)this ))
|
|
{
|
|
dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE;
|
|
}
|
|
|
|
|
|
__ULT_FUNC_CLEANUP;
|
|
|
|
__ULT_FUNC_EXIT(dwRes);
|
|
}
|
|
|
|
DWORD MPCHttpContext::Fsm_ReceiveInput()
|
|
{
|
|
__ULT_FUNC_ENTRY("MPCHttpContext::Fsm_ReceiveInput");
|
|
|
|
DWORD dwRes = HSE_STATUS_SUCCESS;
|
|
|
|
|
|
//
|
|
// Alloc a buffer large enough to hold the request data.
|
|
//
|
|
if(FAILED(m_hsInput.SetSize( m_pECB->cbTotalBytes ))) { dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE; }
|
|
if(FAILED(m_hsInput.write ( m_pECB->lpbData, m_pECB->cbAvailable ))) { dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE; }
|
|
|
|
dwRes = AsyncRead();
|
|
|
|
|
|
__ULT_FUNC_CLEANUP;
|
|
|
|
__ULT_FUNC_EXIT(dwRes);
|
|
}
|
|
|
|
DWORD MPCHttpContext::Fsm_Process()
|
|
{
|
|
__ULT_FUNC_ENTRY("MPCHttpContext::Fsm_Process");
|
|
|
|
HRESULT hr;
|
|
DWORD dwRes = HSE_STATUS_SUCCESS;
|
|
|
|
|
|
if(m_fRequestProcessed == TRUE) __ULT_FUNC_LEAVE;
|
|
|
|
m_hsInput .Rewind();
|
|
m_hsOutput.Reset ();
|
|
|
|
if(FAILED(hr = m_mpcsServer->Process( m_fKeepConnection )))
|
|
{
|
|
if(hr == E_PENDING)
|
|
{
|
|
dwRes = HSE_STATUS_PENDING; __ULT_FUNC_LEAVE;
|
|
}
|
|
|
|
m_fRequestProcessed = TRUE;
|
|
|
|
dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE;
|
|
}
|
|
|
|
m_fRequestProcessed = TRUE;
|
|
|
|
|
|
__ULT_FUNC_CLEANUP;
|
|
|
|
__ULT_FUNC_EXIT(dwRes);
|
|
}
|
|
|
|
DWORD MPCHttpContext::Fsm_SendOutput()
|
|
{
|
|
__ULT_FUNC_ENTRY("MPCHttpContext::Fsm_SendOutput");
|
|
|
|
HSE_SEND_HEADER_EX_INFO headerInfo;
|
|
MPC::string szHeaders;
|
|
DWORD dwRes;
|
|
|
|
|
|
//
|
|
// Built headers.
|
|
//
|
|
SupportAddHeader( szHeaders, "Content-Length", m_hsOutput.GetSize() );
|
|
SupportAddHeader( szHeaders, "Content-Type" , "application/uploadlibrary" );
|
|
|
|
SupportEndHeaders( szHeaders );
|
|
|
|
//
|
|
// Populate HSE_SEND_HEADER_EX_INFO struct.
|
|
//
|
|
headerInfo.pszStatus = szStatus;
|
|
headerInfo.cchStatus = strlen( szStatus );
|
|
headerInfo.pszHeader = szHeaders.c_str();
|
|
headerInfo.cchHeader = szHeaders.length();
|
|
headerInfo.fKeepConn = TRUE;
|
|
|
|
//
|
|
// Send response.
|
|
//
|
|
if(!m_pECB->ServerSupportFunction( m_pECB->ConnID ,
|
|
HSE_REQ_SEND_RESPONSE_HEADER_EX ,
|
|
&headerInfo ,
|
|
NULL ,
|
|
NULL ))
|
|
{
|
|
dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE;
|
|
}
|
|
|
|
//
|
|
// Send data, if present.
|
|
//
|
|
dwRes = AsyncWrite();
|
|
|
|
|
|
__ULT_FUNC_CLEANUP;
|
|
|
|
__ULT_FUNC_EXIT(dwRes);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Methods.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
DWORD MPCHttpContext::Init( /*[in]*/ LPEXTENSION_CONTROL_BLOCK pECB )
|
|
{
|
|
__ULT_FUNC_ENTRY("MPCHttpContext::Init");
|
|
|
|
DWORD dwRes;
|
|
MPC::wstring szURL;
|
|
MPC::wstring szUser;
|
|
|
|
|
|
m_pECB = pECB;
|
|
|
|
|
|
if(FAILED(GetServerVariable( "URL", szURL )))
|
|
{
|
|
szURL = L"DEFAULT";
|
|
}
|
|
|
|
if(FAILED(GetServerVariable( "REMOTE_USER", szUser )))
|
|
{
|
|
szUser = L"";
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
if(pECB->lpszQueryString)
|
|
{
|
|
static MPC::string constNO_RESPONSE_TO_OPEN ( "NO_RESPONSE_TO_OPEN" );
|
|
static MPC::string constNO_RESPONSE_TO_WRITE( "NO_RESPONSE_TO_WRITE" );
|
|
static MPC::string constRESPONSE_TO_OPEN ( "RESPONSE_TO_OPEN" );
|
|
static MPC::string constRESPONSE_TO_WRITE ( "RESPONSE_TO_WRITE" );
|
|
static MPC::string constRANDOM_POINTER_ERROR( "RANDOM_POINTER_ERROR" );
|
|
static MPC::string constFIXED_POINTER_ERROR ( "FIXED_POINTER_ERROR" );
|
|
|
|
|
|
std::vector<MPC::string> vec;
|
|
std::vector<MPC::string> vec2;
|
|
std::vector<MPC::string> vec3;
|
|
MPC::NocaseCompare cmp;
|
|
int i;
|
|
|
|
MPC::SplitAtDelimiter( vec, pECB->lpszQueryString, "&" );
|
|
|
|
for(i=0; i<vec.size(); i++)
|
|
{
|
|
MPC::SplitAtDelimiter( vec2, vec[i].c_str(), "=" );
|
|
|
|
switch( vec2.size() )
|
|
{
|
|
default:
|
|
case 2 : MPC::SplitAtDelimiter( vec3, vec2[1].c_str(), "," );
|
|
case 1 : break;
|
|
case 0 : continue;
|
|
}
|
|
|
|
MPC::string& name = vec2[0];
|
|
|
|
if(cmp( name, constNO_RESPONSE_TO_OPEN ))
|
|
{
|
|
m_Debug_NO_RESPONSE_TO_OPEN = true;
|
|
}
|
|
else if(cmp( name, constNO_RESPONSE_TO_WRITE ))
|
|
{
|
|
m_Debug_NO_RESPONSE_TO_WRITE = true;
|
|
}
|
|
else if(cmp( name, constRESPONSE_TO_OPEN ))
|
|
{
|
|
switch( vec3.size() )
|
|
{
|
|
case 3 : m_Debug_RESPONSE_TO_OPEN_protocol = atol( vec3[2].c_str() );
|
|
case 2 : m_Debug_RESPONSE_TO_OPEN_position = atol( vec3[1].c_str() );
|
|
case 1 : m_Debug_RESPONSE_TO_OPEN_response = atol( vec3[0].c_str() );
|
|
m_Debug_RESPONSE_TO_OPEN = true;
|
|
}
|
|
}
|
|
else if(cmp( name, constRESPONSE_TO_WRITE ))
|
|
{
|
|
switch( vec3.size() )
|
|
{
|
|
case 3 : m_Debug_RESPONSE_TO_WRITE_protocol = atol( vec3[2].c_str() );
|
|
case 2 : m_Debug_RESPONSE_TO_WRITE_position = atol( vec3[1].c_str() );
|
|
case 1 : m_Debug_RESPONSE_TO_WRITE_response = atol( vec3[0].c_str() );
|
|
m_Debug_RESPONSE_TO_WRITE = true;
|
|
}
|
|
}
|
|
else if(cmp( name, constRANDOM_POINTER_ERROR ))
|
|
{
|
|
switch( vec3.size() )
|
|
{
|
|
case 2: m_Debug_RANDOM_POINTER_ERROR_pos_high = atol( vec3[1].c_str() );
|
|
m_Debug_RANDOM_POINTER_ERROR_pos_low = atol( vec3[0].c_str() );
|
|
m_Debug_RANDOM_POINTER_ERROR = true;
|
|
}
|
|
}
|
|
else if(cmp( name, constFIXED_POINTER_ERROR ))
|
|
{
|
|
switch( vec3.size() )
|
|
{
|
|
case 1 : m_Debug_FIXED_POINTER_ERROR_pos = atol( vec3[0].c_str() );
|
|
m_Debug_FIXED_POINTER_ERROR = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
m_mpcsServer = new MPCServer( this, szURL.c_str(), szUser.c_str() );
|
|
|
|
if(m_mpcsServer == NULL)
|
|
{
|
|
dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE;
|
|
}
|
|
|
|
dwRes = AdvanceFSM();
|
|
|
|
|
|
__ULT_FUNC_CLEANUP;
|
|
|
|
__ULT_FUNC_EXIT(dwRes);
|
|
}
|
|
|
|
|
|
HRESULT MPCHttpContext::GetServerVariable( /*[in]*/ LPCSTR szVar, /*[out]*/ MPC::wstring& szValue )
|
|
{
|
|
__ULT_FUNC_ENTRY("MPCHttpContext::GetServerVariable");
|
|
|
|
USES_CONVERSION;
|
|
|
|
HRESULT hr;
|
|
DWORD dwRes;
|
|
LPSTR szData = NULL;
|
|
DWORD dwSize = 0;
|
|
|
|
|
|
m_pECB->GetServerVariable( m_pECB->ConnID, (LPSTR)szVar, NULL, &dwSize );
|
|
|
|
dwRes = ::GetLastError();
|
|
if(dwRes != ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes);
|
|
}
|
|
|
|
__MPC_EXIT_IF_ALLOC_FAILS(hr, szData, new CHAR[dwSize+1]);
|
|
|
|
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, m_pECB->GetServerVariable( m_pECB->ConnID, (LPSTR)szVar, szData, &dwSize ));
|
|
|
|
szValue = A2W( szData );
|
|
hr = S_OK;
|
|
|
|
|
|
__ULT_FUNC_CLEANUP;
|
|
|
|
if(szData) delete [] szData;
|
|
|
|
__ULT_FUNC_EXIT(hr);
|
|
|
|
}
|
|
HRESULT MPCHttpContext::GetRequestSize( /*[out]*/ DWORD& dwCount )
|
|
{
|
|
__ULT_FUNC_ENTRY("MPCHttpContext::GetRequestSize");
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
dwCount = m_hsInput.GetSize();
|
|
hr = S_OK;
|
|
|
|
|
|
__ULT_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT MPCHttpContext::CheckDataAvailable( /*[in] */ DWORD dwCount ,
|
|
/*[out]*/ bool& fAvailable )
|
|
{
|
|
__ULT_FUNC_ENTRY("MPCHttpContext::CheckDataAvailable");
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
fAvailable = (m_hsInput.GetAvailableForRead() >= dwCount);
|
|
hr = S_OK;
|
|
|
|
|
|
__ULT_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT MPCHttpContext::Read( /*[in]*/ void* pBuffer ,
|
|
/*[in]*/ DWORD dwCount )
|
|
{
|
|
__ULT_FUNC_ENTRY("MPCHttpContext::Read");
|
|
|
|
HRESULT hr = m_hsInput.read( pBuffer, dwCount );
|
|
|
|
|
|
__ULT_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT MPCHttpContext::Write( /*[in]*/ const void* pBuffer ,
|
|
/*[in]*/ DWORD dwCount )
|
|
{
|
|
__ULT_FUNC_ENTRY("MPCHttpContext::Write");
|
|
|
|
HRESULT hr = m_hsOutput.write( pBuffer, dwCount );
|
|
|
|
|
|
__ULT_FUNC_EXIT(hr);
|
|
}
|