255 lines
7.1 KiB
C
255 lines
7.1 KiB
C
//-----------------------------------------------------------------------------
|
|
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
|
//
|
|
// rpcisapi.cxx
|
|
//
|
|
// IIS ISAPI extension part of the RPC proxy over HTTP.
|
|
//
|
|
// Exports:
|
|
//
|
|
// BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO *pVer )
|
|
//
|
|
// Returns the version of the spec that this server was built with.
|
|
//
|
|
// BOOL WINAPI HttpExtensionProc( EXTENSION_CONTROL_BLOCK *pECB )
|
|
//
|
|
// This function does all of the work.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Includes:
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include <sysinc.h>
|
|
#include <winsock2.h>
|
|
#include <rpc.h>
|
|
#include <rpcdcep.h>
|
|
#include <rpcerrp.h>
|
|
#include <httpfilt.h>
|
|
#include <httpext.h>
|
|
#include <mbstring.h>
|
|
#include "ecblist.h"
|
|
#include "filter.h"
|
|
#include "olist.h"
|
|
#include "server.h"
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Globals:
|
|
//-----------------------------------------------------------------------------
|
|
|
|
extern SERVER_INFO *g_pServerInfo;
|
|
extern BOOL g_fIsIIS6;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// GetExtensionVersion()
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO *pVer )
|
|
{
|
|
pVer->dwExtensionVersion = MAKELONG( HSE_VERSION_MINOR, HSE_VERSION_MAJOR );
|
|
|
|
ASSERT( sizeof(EXTENSION_DESCRIPTION) <= HSE_MAX_EXT_DLL_NAME_LEN );
|
|
|
|
lstrcpy( pVer->lpszExtensionDesc, EXTENSION_DESCRIPTION );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// ReplyToClient()
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
BOOL ReplyToClient( EXTENSION_CONTROL_BLOCK *pECB,
|
|
char *pBuffer,
|
|
DWORD *pdwSize,
|
|
DWORD *pdwStatus )
|
|
{
|
|
DWORD dwFlags = (HSE_IO_SYNC | HSE_IO_NODELAY);
|
|
|
|
if (!pECB->WriteClient(pECB->ConnID,pBuffer,pdwSize,dwFlags))
|
|
{
|
|
*pdwStatus = GetLastError();
|
|
#ifdef DBG_ERROR
|
|
DbgPrint("ReplyToClient(): failed: %d\n",*pdwStatus);
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
|
|
*pdwStatus = HSE_STATUS_SUCCESS;
|
|
return TRUE;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// ParseQueryString()
|
|
//
|
|
// The query string is in the format:
|
|
//
|
|
// <Index_of_pOverlapped>
|
|
//
|
|
// Where the index is in ASCII Hex. The index is read and converted back
|
|
// to a DWORD then used to locate the SERVER_OVERLAPPED. If its found,
|
|
// return TRUE, else return FALSE.
|
|
//
|
|
// NOTE: "&" is the parameter separator if multiple parameters are passed.
|
|
//-----------------------------------------------------------------------------
|
|
BOOL ParseQueryString( unsigned char *pszQuery,
|
|
SERVER_OVERLAPPED **ppOverlapped,
|
|
DWORD *pdwStatus )
|
|
{
|
|
DWORD dwIndex = 0;
|
|
|
|
pszQuery = AnsiHexToDWORD(pszQuery,&dwIndex,pdwStatus);
|
|
if (!pszQuery)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
*ppOverlapped = GetOverlapped(dwIndex);
|
|
if (*ppOverlapped == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// HttpExtensionProc()
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
DWORD WINAPI HttpExtensionProc( EXTENSION_CONTROL_BLOCK *pECB )
|
|
{
|
|
DWORD dwStatus;
|
|
DWORD dwFlags;
|
|
DWORD dwSize;
|
|
SERVER_INFO *pServerInfo = g_pServerInfo;
|
|
SERVER_OVERLAPPED *pOverlapped = NULL;
|
|
HSE_SEND_HEADER_EX_INFO HeaderEx;
|
|
CHAR *pVerb;
|
|
|
|
pECB->dwHttpStatusCode = STATUS_CONNECTION_OK;
|
|
|
|
if (g_fIsIIS6)
|
|
{
|
|
pVerb = RPC_CONNECT;
|
|
}
|
|
else
|
|
{
|
|
pVerb = POST_STR;
|
|
}
|
|
|
|
//
|
|
// The RPC request must be a post (or RPC_CONNECT for 6.0):
|
|
//
|
|
if (_mbsicmp(pECB->lpszMethod,pVerb))
|
|
{
|
|
dwSize = sizeof(STATUS_MUST_BE_POST_STR) - 1; // don't want to count trailing 0.
|
|
|
|
ReplyToClient(pECB,STATUS_MUST_BE_POST_STR,&dwSize,&dwStatus);
|
|
return HSE_STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Make sure there is no data from the initial BIND in the ECB data buffer:
|
|
//
|
|
// ASSERT(pECB->cbTotalBytes == 0);
|
|
|
|
//
|
|
// Get the connect parameters:
|
|
//
|
|
if (!ParseQueryString(pECB->lpszQueryString,&pOverlapped,&dwStatus))
|
|
{
|
|
dwSize = sizeof(STATUS_POST_BAD_FORMAT_STR) - 1; // don't want to count trailing 0.
|
|
|
|
ReplyToClient(pECB,STATUS_POST_BAD_FORMAT_STR,&dwSize,&dwStatus);
|
|
return HSE_STATUS_SUCCESS;
|
|
}
|
|
|
|
pOverlapped->pECB = pECB;
|
|
|
|
//
|
|
// Add the new ECB to the Active ECB List:
|
|
//
|
|
if (!AddToECBList(g_pServerInfo->pActiveECBList,pECB))
|
|
{
|
|
#ifdef DBG_ERROR
|
|
DbgPrint("HttpExtensionProc(): AddToECBList() failed\n");
|
|
#endif
|
|
FreeOverlapped(pOverlapped);
|
|
pECB->dwHttpStatusCode = STATUS_SERVER_ERROR;
|
|
return HSE_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Submit the first client async read:
|
|
//
|
|
if (!StartAsyncClientRead(pECB,pOverlapped->pConn,&dwStatus))
|
|
{
|
|
#ifdef DBG_ERROR
|
|
DbgPrint("HttpExtensionProc(): StartAsyncClientRead() failed %d\n",dwStatus);
|
|
#endif
|
|
FreeOverlapped(pOverlapped);
|
|
CleanupECB(pECB);
|
|
pECB->dwHttpStatusCode = STATUS_SERVER_ERROR;
|
|
return HSE_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Post the first server read on the new socket:
|
|
//
|
|
IncrementECBRefCount(pServerInfo->pActiveECBList,pECB);
|
|
|
|
if (!SubmitNewRead(pServerInfo,pOverlapped,&dwStatus))
|
|
{
|
|
#ifdef DBG_ERROR
|
|
DbgPrint("HttpExtensionProc(): SubmitNewRead() failed %d\n",dwStatus);
|
|
#endif
|
|
FreeOverlapped(pOverlapped);
|
|
CleanupECB(pECB);
|
|
pECB->dwHttpStatusCode = STATUS_SERVER_ERROR;
|
|
return HSE_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Make sure the server receive thread is up and running:
|
|
//
|
|
if (!CheckStartReceiveThread(g_pServerInfo,&dwStatus))
|
|
{
|
|
#ifdef DBG_ERROR
|
|
DbgPrint("HttpExtensionProc(): CheckStartReceiveThread() failed %d\n",dwStatus);
|
|
#endif
|
|
FreeOverlapped(pOverlapped);
|
|
CleanupECB(pECB);
|
|
pECB->dwHttpStatusCode = STATUS_SERVER_ERROR;
|
|
return HSE_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Send back connection Ok to client, and also set fKeepConn to FALSE.
|
|
//
|
|
dwSize = sizeof(HeaderEx);
|
|
dwFlags = 0;
|
|
memset(&HeaderEx,0,dwSize);
|
|
HeaderEx.fKeepConn = FALSE;
|
|
if (!pECB->ServerSupportFunction(pECB->ConnID,
|
|
HSE_REQ_SEND_RESPONSE_HEADER_EX,
|
|
&HeaderEx,
|
|
&dwSize,
|
|
&dwFlags))
|
|
{
|
|
#ifdef DBG_ERROR
|
|
DbgPrint("HttpExtensionProc(): SSF(HSE_REQ_SEND_RESPONSE_HEADER_EX) failed %d\n",dwStatus);
|
|
#endif
|
|
FreeOverlapped(pOverlapped);
|
|
CleanupECB(pECB);
|
|
pECB->dwHttpStatusCode = STATUS_SERVER_ERROR;
|
|
return HSE_STATUS_ERROR;
|
|
}
|
|
|
|
return HSE_STATUS_PENDING;
|
|
}
|
|
|