windows-nt/Source/XPSP1/NT/com/rpc/runtime/trans/rpcproxy/rpcisapi.c
2020-09-26 16:20:57 +08:00

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;
}