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

521 lines
12 KiB
C++
Raw 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 :
isainst.cpp
Abstract:
This module defines the functions for Internet Server Application
Instance and Instance Pool
Author:
Murali R. Krishnan ( MuraliK ) 9-Sept-1996
Environment:
Win32
Project:
Internet Application Server DLL
Functions Exported:
Revision History:
--*/
/************************************************************
* Include Headers
************************************************************/
# include "isainst.hxx"
# include "dbgutil.h"
# ifdef MTX_ENABLED
#include <vipapi.h>
# endif // MTX_ENABLED
#define IID_DEFINED
# ifdef MTX_ENABLED
#include <txctx.h>
#include <txctx_i.c>
# endif // MTX_ENABLED
#include "isat_i.c"
#include "hreq_i.c"
/************************************************************
* Functions
************************************************************/
PISA_INSTANCE
CreateNewInstance( IN LPCLSID pclsid);
/************************************************************
* Member functions of ISA_INSTANCE
************************************************************/
ISA_INSTANCE::ISA_INSTANCE(VOID)
: m_fInUse ( FALSE),
m_pIsa ( NULL),
m_pHttpReq ( NULL),
m_fInstantiated ( FALSE)
{
InitializeListHead( &m_listEntry);
IF_DEBUG( OBJECT) {
DBGPRINTF(( DBG_CONTEXT, "Created ISA_INSTANCE %08x\n",
this));
}
} // ISA_INSTANCE::ISA_INSTANCE()
ISA_INSTANCE::~ISA_INSTANCE(VOID)
{
DBG_ASSERT( !m_fInUse);
if ( m_pIsa != NULL) {
m_pIsa->Release();
m_pIsa = NULL;
}
if ( m_pHttpReq != NULL) {
m_pHttpReq->Release();
m_pHttpReq = NULL;
}
m_fInUse = FALSE;
m_fInstantiated = FALSE;
IF_DEBUG( OBJECT) {
DBGPRINTF(( DBG_CONTEXT, "Deleted ISA_INSTANCE %08x\n",
this));
}
} // ISA_INSTANCE::~ISA_INSTANCE()
BOOL
ISA_INSTANCE::Instantiate( IN LPCLSID pclsid)
{
HRESULT hr;
DBG_ASSERT( !m_fInstantiated);
DBG_ASSERT( NULL == m_pIsa);
DBG_ASSERT( NULL == m_pHttpReq);
DBG_ASSERT( NULL != pclsid);
m_clsidIsa = *pclsid;
# ifdef VIPER
// Get a Viper transaction context object (should only do once)
hr = CoCreateInstance(CLSID_TransactionContextEx, NULL,
CLSCTX_SERVER,
IID_ITransactionContextEx, (void**)&m_pTxContext);
if (!SUCCEEDED(hr)) goto Err;
# endif
#ifndef VIPER
hr = CoCreateInstance(m_clsidIsa, NULL,
CLSCTX_SERVER, IID_IInetServerApp,
(void ** ) &m_pIsa);
#else
// Create the COMISAPI instance that wraps the ISAPI DLL
hr = m_pTxContext->CreateInstance( m_clisidIsa, IID_IInetServerApp,
(void **) &m_pIsa);
# endif NO_VIPER
if (!SUCCEEDED(hr)) goto Err;
// NYI: Wrap the ECB in a Viper context property
hr = CoCreateInstance(CLSID_HttpRequest, NULL, CLSCTX_SERVER,
IID_IHttpRequest, (void **) &m_pHttpReq);
if (!SUCCEEDED(hr)) goto Err;
// store the context in the created ISA instance
hr = m_pIsa->SetContext( m_pHttpReq);
if (!SUCCEEDED(hr)) goto Err;
Err:
if (!SUCCEEDED(hr)) {
Print();
DBGPRINTF(( DBG_CONTEXT, " Error = %0x8x\n", hr));
#ifdef VIPER
if (m_pTxContext) {
m_pTxContext->Release();
m_ppTxContext = NULL;
}
#endif // VIPER
if ( m_pIsa) {
m_pIsa->Release();
m_pIsa = NULL;
}
if ( m_pHttpReq) {
m_pHttpReq->Release();
m_pHttpReq = NULL;
}
} else {
m_fInstantiated = TRUE;
}
DBGPRINTF(( DBG_CONTEXT,
"[%08x]::Instantiate( %08x) returns hr=%08x \n",
this, pclsid, hr
));
return ( (SUCCEEDED(hr)? TRUE : FALSE));
} // ISA_INSTANCE::Instantiate()
HRESULT
ISA_INSTANCE::ProcessRequest(IN EXTENSION_CONTROL_BLOCK * pecb,
OUT LPDWORD pdwStatus)
{
HRESULT hr = E_FAIL;
DBG_ASSERT( m_fInstantiated);
DBG_ASSERT( NULL != m_pIsa);
DBG_ASSERT( NULL != m_pHttpReq);
DBG_ASSERT( !m_fInUse);
m_fInUse = TRUE;
hr = m_pHttpReq->SetECB( (long ) pecb);
if ( SUCCEEDED( hr)) {
hr = m_pIsa->ProcessRequest( pdwStatus);
}
m_fInUse = FALSE;
IF_DEBUG( OBJECT) {
DBGPRINTF(( DBG_CONTEXT,
"[%08x]ISA_INSTANCE::ProcessRequest() returns %08x"
,
this, hr));
}
return ( hr);
} // ISA_INSTANCE::ProcessRequest()
void
ISA_INSTANCE::Print(VOID) const
{
DBGPRINTF(( DBG_CONTEXT,
"ISA_INSTANCE(%08x):"
" pIsa=%08x; pHttpReq=%08x; "
" fInUse=%d; fInstantiated=%d"
"\n"
,
this, m_pIsa, m_pHttpReq,
m_fInUse, m_fInstantiated
));
return;
} // ISA_INSTANCE::Print()
/************************************************************
* Member functions of ISA_INSTANCE
************************************************************/
ISA_INSTANCE_POOL::ISA_INSTANCE_POOL(VOID)
: m_fInstantiated ( FALSE),
m_nFreeEntries ( 0),
m_nActiveEntries( 0)
{
m_rgchProgId[0] = L'\0';
InitializeCriticalSection( & m_csLock);
InitializeListHead( &m_lActiveEntries);
InitializeListHead( &m_lFreeEntries);
IF_DEBUG( OBJECT) {
DBGPRINTF(( DBG_CONTEXT, "Created ISA_INSTANCE_POOL %08x\n",
this));
}
} // ISA_INSTANCE_POOL::ISA_INSTANCE_POOL()
ISA_INSTANCE_POOL::~ISA_INSTANCE_POOL(VOID)
{
PLIST_ENTRY pl;
DBG_ASSERT( IsListEmpty( &m_lActiveEntries));
DBG_ASSERT( 0 == m_nActiveEntries);
// free up all the instances in the pool
for( pl = m_lFreeEntries.Flink;
pl != &m_lFreeEntries;
m_nFreeEntries-- ) {
PLIST_ENTRY plNext;
PISA_INSTANCE pisaInstance =
CONTAINING_RECORD( pl, ISA_INSTANCE, m_listEntry);
plNext = pl->Flink;
DBG_ASSERT( pisaInstance);
RemoveEntryList( pl);
delete pisaInstance;
pl = plNext;
} // for
DBG_ASSERT( IsListEmpty(&m_lFreeEntries));
DBG_ASSERT( 0 == m_nFreeEntries);
m_fInstantiated = FALSE;
DeleteCriticalSection( & m_csLock);
IF_DEBUG( OBJECT) {
DBGPRINTF(( DBG_CONTEXT, "Deleted ISA_INSTANCE_POOL %08x\n",
this));
}
} // ISA_INSTANCE_POOL::~ISA_INSTANCE_POOL()
VOID
ISA_INSTANCE_POOL::Print(VOID)
{
PLIST_ENTRY pl;
DBGPRINTF(( DBG_CONTEXT,
"ISA_INSTANCE_POOL (%08x):"
" ProgId = %ws. Instantiated=%d"
" Instances #Free = %d; #Active = %d"
"\n"
,
this, m_rgchProgId,
m_fInstantiated,
m_nFreeEntries, m_nActiveEntries
));
Lock();
// Print all free entries
DBGPRINTF(( DBG_CONTEXT, " Free Entries \n"));
for( pl = m_lFreeEntries.Flink; pl != &m_lFreeEntries;
pl = pl->Flink) {
PISA_INSTANCE pisaInstance =
CONTAINING_RECORD( pl, ISA_INSTANCE, m_listEntry);
pisaInstance->Print();
} // for
// Print all active entries
DBGPRINTF(( DBG_CONTEXT, " Active Entries \n"));
for( pl = m_lActiveEntries.Flink; pl != &m_lActiveEntries;
pl = pl->Flink) {
PISA_INSTANCE pisaInstance =
CONTAINING_RECORD( pl, ISA_INSTANCE, m_listEntry);
pisaInstance->Print();
} // for
Unlock();
return;
} // ISA_INSTANCE_POOL::Print()
BOOL
ISA_INSTANCE_POOL::Instantiate( IN LPCWSTR pszProgId)
/*++
ISA_INSTANCE_POOL::Instantiate()
o This function instantiates the instance pool. It stores the
program ID supplied as well as the class ID for the given object.
In the future new instances maybe created in this instance pool
using these values.
Arguments:
pszProgId - pointer to null-terminated-string containing the ProgID
for instance objects
Returns:
TRUE on success and FALSE if there is any error.
--*/
{
HRESULT hr;
DBG_ASSERT( !m_fInstantiated);
DBG_ASSERT( m_rgchProgId[0] == L'\0');
// Get the clsid for the instance
hr = CLSIDFromProgID( pszProgId, &m_clsidIsa);
if (!SUCCEEDED(hr)) {
Print();
DBGPRINTF(( DBG_CONTEXT,
"ISA_INSTANCE_POOL::Instantiate(%ws) Error = %0x8x\n",
pszProgId, hr));
} else {
// make a local copy of the ProgId
lstrcpynW( m_rgchProgId, pszProgId,
(sizeof( m_rgchProgId) - 1)/sizeof(WCHAR));
m_fInstantiated = TRUE;
}
return ( (SUCCEEDED(hr)? TRUE : FALSE));
} // ISA_INSTANCE_POOL::Instantiate()
PISA_INSTANCE
ISA_INSTANCE_POOL::GetInstance(void)
{
PISA_INSTANCE pisa = NULL;
DBG_ASSERT( m_fInstantiated);
//
// 1. Look for a free instance
// 2. If a free one is found,
// move it to active list and return pointer for the same
// 3. If no free instance is found, create a new instance
// 4. Send the new instance off to the caller after putting it in
// the active list.
//
if ( m_nFreeEntries > 0) {
// Aha! there may be free entries, lock and pull one out.
Lock();
if ( m_nFreeEntries > 0) {
// remove an item from the list
PLIST_ENTRY pl = m_lFreeEntries.Flink;
RemoveEntryList( pl);
pisa = CONTAINING_RECORD( pl, ISA_INSTANCE, m_listEntry);
DBG_ASSERT( pisa != NULL);
m_nFreeEntries--;
DBG_ASSERT( m_nFreeEntries >= 0);
InsertTailList( &m_lActiveEntries, pl);
m_nActiveEntries++;
DBG_ASSERT( m_nActiveEntries > 0);
}
Unlock();
}
if ( NULL == pisa) {
// we did not find an item. we need to create a new instance
// create a new instance
pisa = CreateNewInstance( &m_clsidIsa);
if ( pisa != NULL) {
// Successfully created a new instance. Add it to the list.
Lock();
InsertTailList( &m_lActiveEntries, &pisa->m_listEntry);
m_nActiveEntries++;
DBG_ASSERT( m_nActiveEntries > 0);
Unlock();
} else {
// there was an error in creating the instance.
}
}
return ( pisa);
} // ISA_INSTANCE_POOL::GetInstance()
BOOL
ISA_INSTANCE_POOL::ReleaseInstance( PISA_INSTANCE pisaInstance)
{
DBG_ASSERT( NULL != pisaInstance);
//
// 1. Remove the request from the active list
// 2. Add this new item to the free list
// 3. Adjust the counts appropriately
//
Lock();
DBG_ASSERT( m_nActiveEntries > 0);
RemoveEntryList( &pisaInstance->m_listEntry);
m_nActiveEntries--;
DBG_ASSERT( m_nActiveEntries >= 0);
InsertHeadList( &m_lFreeEntries, &pisaInstance->m_listEntry);
m_nFreeEntries++;
DBG_ASSERT( m_nFreeEntries > 0);
Unlock();
return (TRUE);
} // ISA_INSTANCE_POOL::ReleaseInstance()
PISA_INSTANCE
CreateNewInstance( IN LPCLSID pclsid)
{
PISA_INSTANCE pisa;
pisa = new ISA_INSTANCE();
if ( NULL == pisa ) {
DBGPRINTF(( DBG_CONTEXT,
"Creating ISA_INSTANCE failed. \n"
));
SetLastError( ERROR_NOT_ENOUGH_MEMORY);
} else {
if ( !pisa->Instantiate( pclsid )) {
DBGPRINTF(( DBG_CONTEXT,
"[%08x]::Instantiate( %08x) failed. Error=%d \n",
pisa, pclsid, GetLastError()
));
delete pisa;
pisa = NULL;
}
}
return ( pisa);
} // CreateNewInstance()
/************************ End of File ***********************/