2025-04-27 07:49:33 -04:00

475 lines
12 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1995-1996 Microsoft Corporation
Module Name :
cisatest.cpp
Abstract:
This module defines the Test ISAPI DLL for driving ComIsapi
Author:
Murali R. Krishnan ( MuraliK ) 27-Aug-1996
Project:
Internet Application Server DLL
Revision History:
--*/
/************************************************************
* Include Headers
************************************************************/
#include <objbase.h>
#include <iisext.h>
#include <assert.h>
#include <vipapi.h>
#define IID_DEFINED
#include <txctx.h>
#include <txctx_i.c>
#include "cisa_i.c"
#include "cisa.h"
#include "cpecb_i.c"
#include "cpecb.h"
# include "dbgutil.h"
/************************************************************
* Prototypes
************************************************************/
HRESULT IsapiToComisapi(EXTENSION_CONTROL_BLOCK* pECB, DWORD* pdwRet);
HRESULT CreateIsapiInstance( ITransactionContextEx * *,
IComIsapi * * ppComIsapi,
IcpECB ** ppIcpECB);
/************************************************************
* Variable Declarations
************************************************************/
# ifdef COINIT_NOEX
static DWORD g_dwTLSIndex = (DWORD)-1; // COM initialization flag
# endif // COINIT_NOEX
BOOL g_fComInit = FALSE;
IComIsapi * g_pComIsapi = NULL;
IcpECB * g_pIcpECB = NULL;
ITransactionContextEx * g_pTxContext = NULL;
DECLARE_DEBUG_PRINTS_OBJECT();
DECLARE_DEBUG_VARIABLE();
CRITICAL_SECTION g_csInit;
BOOL g_fInitSink = FALSE;
/************************************************************
* Functions
************************************************************/
// functions
// DllMain
// Note IIS thread pools so we won't reliably get DLL_THREAD_ATTACH
// messages. Avoid problems by acquiring all resources on
// DLL_PROCESS_ATTACH and deallocating on DLL_PROCESS_DETACH.
//
BOOL WINAPI DllMain(
HINSTANCE hinstDll,
DWORD fdwReason,
LPVOID lpvContext)
{
HRESULT hr;
switch (fdwReason) {
case DLL_PROCESS_ATTACH: {
CREATE_DEBUG_PRINT_OBJECT( "cisatest");
if ( !VALID_DEBUG_PRINT_OBJECT()) {
return ( FALSE);
}
SET_DEBUG_FLAGS( DEBUG_OBJECT | DEBUG_IID | DEBUG_ERROR);
InitializeCriticalSection( & g_csInit);
#ifdef COINIT_NOEX
// allocate thread local storage
if ((g_dwTLSIndex = TlsAlloc()) == -1)
return FALSE;
# else
hr = CoInitializeEx( NULL,
(COINIT_MULTITHREADED |
COINIT_DISABLE_OLE1DDE |
COINIT_SPEED_OVER_MEMORY)
);
g_fComInit = (hr == S_OK);
DBGPRINTF(( DBG_CONTEXT,
"\tCoInitializeEx( NULL, %08x) returns %08x\n",
(COINIT_MULTITHREADED |
COINIT_DISABLE_OLE1DDE |
COINIT_SPEED_OVER_MEMORY),
hr
));
# endif // ifndef COINIT_NOEX
// IIS thread pools, we don't want thread notifications
DisableThreadLibraryCalls(hinstDll);
break;
}
case DLL_PROCESS_DETACH:
#ifdef COINIT_NOEX
if (g_dwTLSIndex != -1)
TlsFree(g_dwTLSIndex);
# else
if (g_pComIsapi) {
g_pComIsapi->Release();
}
if ( g_fComInit) {
CoUninitialize();
}
# endif // COINIT_NOEX
DeleteCriticalSection( & g_csInit);
DELETE_DEBUG_PRINT_OBJECT();
break;
}
return TRUE;
} // DllMain()
// GetExtensionVerion
// Standard versioning entry point from IIS.
//
BOOL WINAPI
GetExtensionVersion(HSE_VERSION_INFO* pVer)
{
HRESULT hr;
pVer->dwExtensionVersion = MAKELONG(HSE_VERSION_MINOR, HSE_VERSION_MAJOR );
strncpy(pVer->lpszExtensionDesc, "Test IsapiToComisapi",
HSE_MAX_EXT_DLL_NAME_LEN);
#ifdef CACHE_INSTANCE
#ifdef COINIT_NOEX
// Initialize COM
// FIX: need to uninitialize but thread detach a problem
if (TlsGetValue(g_dwTLSIndex) == FALSE) {
hr = CoInitialize(NULL);
if (!SUCCEEDED(hr)) goto Err;
TlsSetValue(g_dwTLSIndex, (void*)TRUE);
}
# endif // COINIT_NOEX
hr = CreateIsapiInstance( &g_pTxContext, &g_pComIsapi, &g_pIcpECB);
if (!SUCCEEDED(hr)) goto Err;
Err:
DBGPRINTF(( DBG_CONTEXT,
"g_fComInit=%d;"
"CreateInstance returns hr=%08x;"
"pComIsapi=%08x; pIcpECB=%08x\n"
,
g_fComInit,
hr,
g_pComIsapi,
g_pIcpECB));
#else
hr = S_OK;
#endif // !CACHE_INSTANCE
return (hr == S_OK) ? TRUE : FALSE;
} // GetExtensionVersion()
BOOL WINAPI
TerminateExtension( IN DWORD dwFlags)
{
DBGPRINTF(( DBG_CONTEXT, "TerminateExtension (%08x)\n", dwFlags));
if (g_pComIsapi) {
g_pComIsapi->Release();
g_pComIsapi = NULL;
}
DBGPRINTF(( DBG_CONTEXT, "Cleaned up g_pComIsapi\n"));
if (g_pIcpECB) {
g_pIcpECB->Release();
g_pIcpECB = NULL;
}
DBGPRINTF(( DBG_CONTEXT, "Cleaned up g_pIcpECB\n"));
#ifndef COINIT_NOEX
if ( g_fComInit) {
CoUninitialize();
g_fComInit = FALSE;
}
# endif // COINIT_NOEX
DBGPRINTF(( DBG_CONTEXT, "Cleaned up COM\n"));
return ( TRUE);
} // TerminateExtension()
// HttpExtensionProc
// Standard invocation entry point from IIS.
//
DWORD WINAPI
HttpExtensionProc( EXTENSION_CONTROL_BLOCK* pECB)
{
DWORD dwRet;
try {
if (!SUCCEEDED(IsapiToComisapi(pECB, &dwRet)))
dwRet = HSE_STATUS_ERROR;
}
catch(...) {
DBG_ASSERT(FALSE);
dwRet = HSE_STATUS_ERROR;
}
return dwRet;
} // HttpExtensionProc()
HRESULT
CreateIsapiInstance( ITransactionContextEx * * ppTxContext,
IComIsapi * * ppComIsapi,
IcpECB ** ppIcpECB)
{
HRESULT hr;
# ifdef VIPER
// Get a Viper transaction context object (should only do once)
hr = CoCreateInstance(CLSID_TransactionContextEx, NULL,
CLSCTX_SERVER,
IID_ITransactionContextEx, (void**)ppTxContext);
if (!SUCCEEDED(hr)) goto Err;
# endif
// Get the clsid for this ISAPI DLL
CLSID clsidISAPIDLL;
hr = CLSIDFromProgID(L"MSCISA_FOO.DLL", &clsidISAPIDLL);
if (!SUCCEEDED(hr)) goto Err;
#ifndef VIPER
hr = CoCreateInstance(clsidISAPIDLL, NULL,
CLSCTX_SERVER, IID_IComIsapi,
(void ** ) ppComIsapi);
#else
// Create the COMISAPI instance that wraps the ISAPI DLL
hr = (*ppTxContext)->CreateInstance(clsidISAPIDLL, IID_IComIsapi,
(void**)ppComIsapi);
# endif NO_VIPER
if (!SUCCEEDED(hr)) goto Err;
// Wrap the ECB in a Viper context property
hr = CoCreateInstance(CLSID_cpECB, NULL, CLSCTX_SERVER,
IID_IcpECB, (void**) ppIcpECB);
if (!SUCCEEDED(hr)) goto Err;
Err:
if (!SUCCEEDED(hr)) {
#ifdef VIPER
if (*ppTxContext) {
(*ppTxContext)->Release();
*ppTxContext = NULL;
}
#endif // VIPER
if ( *ppComIsapi) {
(*ppComIsapi)->Release();
*ppComIsapi = NULL;
}
if ( *ppIcpECB) {
(*ppIcpECB)->Release();
*ppIcpECB = NULL;
}
}
return ( hr);
} // CreateIsapiInstance()
// IsapiToComisapi
// Invoke the ISAPI DLL as a COMISAPI component
//
HRESULT
IsapiToComisapi(EXTENSION_CONTROL_BLOCK* pECB, DWORD* pdwRet)
{
HRESULT hr = S_OK;
IComIsapi* pComIsapi = NULL;
ITransactionContextEx * pTxContext = NULL;
IcpECB* pcpECB = NULL;
IN_CISA_WIRE_ECB ince;
OUT_CISA_WIRE_ECB outce;
# ifdef COINIT_NOEX
// Initialize COM
// FIX: need to uninitialize but thread detach a problem
if (TlsGetValue(g_dwTLSIndex) == FALSE) {
hr = CoInitialize(NULL);
if (!SUCCEEDED(hr)) goto Err;
TlsSetValue(g_dwTLSIndex, (void*)TRUE);
}
# endif // COINIT_NOEX
#ifdef CACHE_INSTANCE
DBG_ASSERT( NULL != g_pComIsapi);
g_pComIsapi->AddRef();
pComIsapi = g_pComIsapi;
DBG_ASSERT( NULL != g_pIcpECB);
g_pIcpECB->AddRef();
pcpECB = g_pIcpECB;
# ifdef VIPER
g_pTxContext->AddRef();
pTxContext = g_pTxContext;
# endif
#else
hr = CreateIsapiInstance( &pTxContext, &pComIsapi, &pcpECB);
#endif // CACHE_INSTANCE
if (!SUCCEEDED(hr)) goto Err;
// call the SetECB only for non-cached IcpECB,
// provided the cached g_IcpECB is build properly
// NYI: The cached ECB does not have proper function pointers set
// so we call SetECB() now which smartly initializes only once!
//
hr = pcpECB->SetECB(sizeof(EXTENSION_CONTROL_BLOCK),
(unsigned char*)pECB);
if (!SUCCEEDED(hr)) goto Err;
#ifdef CACHE_INSTANCE
if ( !g_fInitSink) {
EnterCriticalSection( &g_csInit);
if ( !g_fInitSink) {
hr = pComIsapi->SetIsapiSink( pcpECB);
g_fInitSink = ( hr == S_OK);
DBGPRINTF(( DBG_CONTEXT,
" pComIsapi(%08x)->SetIsapiSink(%08x) => hr = %08x\n",
pComIsapi, pcpECB, hr
));
}
LeaveCriticalSection( &g_csInit);
}
if (!SUCCEEDED(hr)) goto Err;
#endif // !CACHE_INSTANCE
#ifdef WIRE_ECB
ince.ConnID = (DWORD ) pECB->ConnID;
ince.lpszMethod = pECB->lpszMethod;
ince.lpszQueryString = pECB->lpszQueryString;
ince.lpszPathInfo = pECB->lpszPathInfo;
ince.lpszPathXlated = pECB->lpszPathTranslated;
ince.lpszContentType = pECB->lpszContentType;
ince.cbTotalBytes = pECB->cbTotalBytes;
//
// Clients can send more bytes then are indicated in their
// Content-Length header. Adjust byte counts so they match
//
ince.cbAvailable = pECB->cbAvailable;
// The following is broken for now :-( -- no additional data
// ince.lpbData = pECB->lpbData;
outce.dwHseStatus = HSE_STATUS_SUCCESS;
outce.dwHttpStatusCode= pECB->dwHttpStatusCode;
outce.cbLogData = 0;
// following copy of lpchLogData is not required during invocation
// we will copy the contents on return
// outce.lpchLogData = (CHAR *) pECB->lpszLogData;
#endif // WIRE_ECB
// Invoke the wrapped ISAPI DLL
hr = pComIsapi->HttpExtensionProc(&ince,
&outce);
*pdwRet = outce.dwHseStatus;
# ifdef WIRE_ECB
// Copy the output parameters to the ECB block
if ( SUCCEEDED(hr)) {
pECB->dwHttpStatusCode = outce.dwHttpStatusCode;
// We will not support the log data now :-(
// memcpy( pECB->lpszLogData, outce.lpchLogData, outce.cbLogData);
}
# endif // WIRE_ECB
Err:
if ( !SUCCEEDED(hr)) {
CHAR pchBuff[1000];
wsprintf( pchBuff,
"\nCisaTest:[%d]"
"IsapiToComIsapi Failed. hr=%08x. pcpECB=%08x;"
"pComIsapi=%08x; pTxContext = %08x\n"
,
GetCurrentThreadId(),
hr, pcpECB, pComIsapi, pTxContext);
OutputDebugString(pchBuff);
}
// Release resources
if (pcpECB) {
pcpECB->Release();
}
if (pComIsapi) {
pComIsapi->Release();
}
if (pTxContext) {
pTxContext->Release();
}
return hr;
} // IsapiToComisapi()