|
|
/*=====================================================================*
Copyright (c) 1995-1997 Microsoft Corporation
Module Name : wamxbase.cxx
Abstract: Declaration of WAM_EXEC_BASE Object
Author:
David L. Kaplan ( DaveK ) 26-June-1997
Environment: User Mode - Win32
Project:
WAM and ASP DLLs
Revision History:
======================================================================*/
# include "isapip.hxx"
# include "wamxbase.hxx"
# include "gip.h"
// MIDL-generated
# include "iwr.h"
/*---------------------------------------------------------------------*
WAM_EXEC_BASE::WAM_EXEC_BASE
Constructor
*/ WAM_EXEC_BASE::WAM_EXEC_BASE( ) : m_dwThreadIdIIS ( 0 ) // threadid 0 can't happen in IIS
, m_dwThreadIdISA ( 0 ) // threadid 0 can't happen in IIS
, m_pIWamReqIIS ( NULL ) , m_pIWamReqInproc ( NULL ) , m_pIWamReqSmartISA( NULL ) , m_gipIWamRequest ( 0 ) , _dwIsaKeepConn ( KEEPCONN_OLD_ISAPI ) // per fix to #117107
{
IF_DEBUG( WAM_IWAMREQ_REFS ) {
//
// NOTE when WAM_IWAMREQ_REFS flag is set, we use
// m_dwSignature as a ref count for gip get/release
// (rather than add another debug-only member)
//
m_dwSignature = 0; }
}
/*---------------------------------------------------------------------*
WAM_EXEC_BASE::InitWamExecBase
Inits this structure by setting interface ptr members based on whether we are in-proc or oop.
*/ HRESULT WAM_EXEC_BASE::InitWamExecBase( IWamRequest * pIWamRequest ) {
HRESULT hr = NOERROR;
//
// cache pointer passed to us by IIS
// and thread id on which IIS called us
//
// NOTE we don't addref the ptr because we may not
// actually use it. If we decide to use the ptr
// (e.g. in-proc, or oop-smart-ISA on IIS thread),
// we will addref then.
//
m_pIWamReqIIS = pIWamRequest; m_dwThreadIdIIS = GetCurrentThreadId();
if ( m_fInProcess ) {
//
// In-Proc
//
// Cache and addref wamreq, since we will use its ptr
//
m_pIWamReqInproc = pIWamRequest; m_pIWamReqInproc->AddRef();
// Remember wamreq in m_pIWamReqSmartISA as well to make
// wamreq available in all cases for smart (caching)
// ISAPIs like ASP simply by referring to m_pIWamReqSmartISA
m_pIWamReqSmartISA = m_pIWamReqInproc;
} else {
//
// Out-Proc
//
// Register wamreq with gip-master
//
// NOTE gip.Register addref's implicitly
//
hr = RegisterIWamRequest( pIWamRequest );
}
return hr;
} // WAM_EXEC_BASE::InitWamExecBase
/*---------------------------------------------------------------------*
WAM_EXEC_BASE::CleanupWamExecBase
Cleans up this structure by setting interface ptr members based on whether we are in-proc or oop.
*/ VOID WAM_EXEC_BASE::CleanupWamExecBase( ) {
if ( m_fInProcess ) {
//
// In-proc
//
// Release the member wamreq ptr we cached at init
//
DBG_ASSERT( AssertInpValid() );
m_pIWamReqInproc->Release();
m_pIWamReqInproc = NULL; m_pIWamReqSmartISA = NULL;
} else {
//
// Out-proc
//
// Revoke the gip cookie
//
DBG_ASSERT( AssertOopValid() );
RevokeIWamRequest();
}
return;
} // WAM_EXEC_BASE::CleanupWamExecBase
/*---------------------------------------------------------------------*
WAM_EXEC_BASE::RegisterIWamRequest For oop use only. Registers our W3-thread IWamRequest ptr with gip-master.
Arguments: None
Returns: HRESULT */ HRESULT WAM_EXEC_BASE::RegisterIWamRequest( IWamRequest * pIWamRequest ) {
HRESULT hr = NOERROR;
DBG_ASSERT ( !m_fInProcess ); DBG_ASSERT( pIWamRequest );
//
// Register iwamreq ptr with gip-master
//
if ( FAILED( hr = g_GIPAPI.Register( pIWamRequest , IID_IWamRequest , &m_gipIWamRequest ))) {
DBGPRINTF(( DBG_CONTEXT , "g_GIPAPI.Register failed " "hr(%08x) " "m_gipIWamRequest(%08x) " "\n" , hr , m_gipIWamRequest ));
} else {
DBG_ASSERT( AssertOopValid() );
}
return hr;
}
/*---------------------------------------------------------------------*
WAM_EXEC_BASE::RevokeIWamRequest If oop, revokes our gip-cookie.
Arguments: None
Returns: Nothing
*/ VOID WAM_EXEC_BASE::RevokeIWamRequest( ) {
DBG_ASSERT( AssertOopValid() );
//
// Revoke the gip-cookie we got from gip-master at init
//
g_GIPAPI.Revoke( m_gipIWamRequest );
return; }
/*---------------------------------------------------------------------*
WAM_EXEC_BASE::GetInterfaceForThread Caches a current-thread-valid IWamRequest ptr in m_pIWamReqSmartISA
Arguments: None
Returns: HRESULT */ HRESULT WAM_EXEC_BASE::GetInterfaceForThread( ) {
HRESULT hr = NOERROR;
DBG_ASSERT( m_pIWamReqSmartISA == NULL ); DBG_ASSERT( m_dwThreadIdISA == 0 ); DBG_ASSERT( AssertOopValid() );
m_dwThreadIdISA = GetCurrentThreadId();
IF_DEBUG( WAM_THREADID ) {
DBGPRINTF(( DBG_CONTEXT , "WAM_EXEC_BASE(%08x)::GetInterfaceForThread " "m_dwThreadIdIIS(%d) " "m_dwThreadIdISA(%d) " "\n" , this , m_dwThreadIdIIS , m_dwThreadIdISA ));
}
if ( m_dwThreadIdISA == m_dwThreadIdIIS ) {
//
// ISA called us on mainline (IIS) thread
// so we can simply use cached ptr passed in by IIS.
//
m_pIWamReqSmartISA = m_pIWamReqIIS;
//
// addref the ptr since we are using it.
//
m_pIWamReqSmartISA->AddRef();
} else {
//
// ISA called us on its own thread
// so we must get a ptr from gip.
//
hr = GetInterfaceFromGip( &m_pIWamReqSmartISA );
IF_DEBUG( WAM_THREADID ) {
DBGPRINTF(( DBG_CONTEXT , "GetInterfaceFromGip returned %d" "\n" , hr ));
DBGPRINTF(( DBG_CONTEXT , "m_dwThreadIdISA(%d)" "\n" , m_dwThreadIdISA ));
}
}
return hr;
} // WAM_EXEC_BASE::GetInterfaceForThread
/*---------------------------------------------------------------------*
WAM_EXEC_BASE::ReleaseInterfaceForThread Releases the IWamRequest ptr cached in m_pIWamReqSmartISA
Arguments: None
Returns: HRESULT */ HRESULT WAM_EXEC_BASE::ReleaseInterfaceForThread( ) {
DBG_ASSERT( AssertOopValid() );
if ( m_pIWamReqSmartISA == NULL ) {
//
// In some races, ISA-thread ptr was already released.
// This is harmless, so we no-op.
//
DBGPRINTF(( DBG_CONTEXT , "WAM_EXEC_BASE(%08x)::ReleaseInterfaceForThread\n" "\t Cached ISA-thread ptr already released\n" "\t m_dwThreadIdISA(%d)\n" "\t Current thread id(%d)\n" "\t m_pIWamReqSmartISA(%d)\n" , this , m_dwThreadIdISA , GetCurrentThreadId() , m_pIWamReqSmartISA ));
return NOERROR;
}
DBG_ASSERT( AssertSmartISAValid() );
if ( m_dwThreadIdISA != GetCurrentThreadId() ) {
//
// If thread id's don't match, we can't release
//
DBGPRINTF(( DBG_CONTEXT , "WAM_EXEC_BASE(%08x)::ReleaseInterfaceForThread\n" "\t Wrong thread error\n" "\t m_dwThreadIdISA(%d)\n" "\t Current thread id(%d)\n" "\t m_pIWamReqSmartISA(%d)\n" , this , m_dwThreadIdISA , GetCurrentThreadId() , m_pIWamReqSmartISA ));
//
// Aha! If COM can return this, so can we ...
//
return RPC_E_WRONG_THREAD;
}
m_pIWamReqSmartISA->Release(); m_pIWamReqSmartISA = NULL; m_dwThreadIdISA = 0;
return NOERROR;
}
/*---------------------------------------------------------------------*
WAM_EXEC_BASE::GetIWamRequest Returns a thread-valid IWamRequest ptr.
Arguments: ppIWamRequest - returned ptr
Returns: HRESULT */ HRESULT WAM_EXEC_BASE::GetIWamRequest( IWamRequest ** ppIWamRequest ) {
HRESULT hrRet = NOERROR;
IF_DEBUG( WAM_IWAMREQ_REFS ) {
//
// NOTE when WAM_IWAMREQ_REFS flag is set, we use
// m_dwSignature as a ref count for gip get/release
// (rather than add another debug-only member)
//
m_dwSignature++;
DBGPRINTF(( DBG_CONTEXT , "WAM_EXEC_BASE(%08x)::GetIWamRequest" " %d -> %d" "\n" , this , m_dwSignature - 1 , m_dwSignature )); }
if ( m_fInProcess ) {
//
// In-Proc: simply return our cached W3-thread ptr
//
DBG_ASSERT( AssertInpValid() );
*ppIWamRequest = m_pIWamReqInproc;
IF_DEBUG( WAM_REFCOUNTS ) {
DBGPRINTF(( DBG_CONTEXT , "WAM_EXEC_BASE(%08x)::GetIWamRequest" "\tIn-proc m_pIWamReqInproc(%08x)" "\n" , this , m_pIWamReqInproc )); }
} else {
//
// Out-of-Proc:
// If we are dealing with a 'smart ISA', use ISA-thread ptr
//
// Else if we are on 'IIS thread', use 'IIS ptr'
//
// Else, get a ptr from gip-master
//
//
DBG_ASSERT( AssertOopValid() );
if ( m_pIWamReqSmartISA ) {
//
// FAST
//
// 'Smart ISA' ==> use ISA-thread ptr
//
DBG_ASSERT( AssertSmartISAValid() );
*ppIWamRequest = m_pIWamReqSmartISA;
IF_DEBUG( WAM_REFCOUNTS ) {
DBGPRINTF(( DBG_CONTEXT , "WAM_EXEC_BASE(%08x)::GetIWamRequest" "\tOut-of-proc optimized - smart ISA: " "m_pIWamReqSmartISA(%08x)" "\n" , this , m_pIWamReqSmartISA )); }
} else if ( GetCurrentThreadId() == m_dwThreadIdIIS ) {
//
// FAST
//
// We are on 'IIS thread' ==> use 'IIS ptr'
// NOTE we addref it as a precaution
//
*ppIWamRequest = m_pIWamReqIIS; m_pIWamReqIIS->AddRef();
IF_DEBUG( WAM_REFCOUNTS ) {
DBGPRINTF(( DBG_CONTEXT , "WAM_EXEC_BASE(%08x)::GetIWamRequest" "\tOut-of-proc optimized - IIS thread: " "m_pIWamReqIIS(%08x)" "\n" , this , m_pIWamReqIIS )); }
} else {
//
// SLOW :-(
//
// ISA is not smart and we are not on IIS thread
// ==> must get a ptr from gip
//
hrRet = GetInterfaceFromGip( ppIWamRequest );
IF_DEBUG( WAM_REFCOUNTS ) {
DBGPRINTF(( DBG_CONTEXT , "WAM_EXEC_BASE(%08x)::GetIWamRequest" "\tOut-of-proc NOT optimized: *ppIWamRequest(%08x)" "\n" , this , *ppIWamRequest )); }
}
} // ( m_fInProcess )
return hrRet;
} // WAM_EXEC_BASE::GetIWamRequest
/*---------------------------------------------------------------------*
WAM_EXEC_BASE::ReleaseIWamRequest Releases an IWamRequest ptr, covering whether in-proc or out-proc.
Arguments: pIWamRequest - ptr to release
Returns: Nothing
*/ VOID WAM_EXEC_BASE::ReleaseIWamRequest( IWamRequest * pIWamRequest ) {
IF_DEBUG( WAM_IWAMREQ_REFS ) {
//
// NOTE when WAM_IWAMREQ_REFS flag is set, we use
// m_dwSignature as a ref count for gip get/release
// (rather than add another debug-only member)
//
m_dwSignature--;
DBGPRINTF(( DBG_CONTEXT , "WAM_EXEC_BASE(%08x)::ReleaseIWamRequest" " %d -> %d" "\n" , this , m_dwSignature + 1 , m_dwSignature )); }
if ( m_fInProcess ) {
DBG_ASSERT( AssertInpValid() ); //
// In-Proc: no-op
//
return; }
if ( m_pIWamReqSmartISA && (pIWamRequest == m_pIWamReqSmartISA) ) { DBG_ASSERT( AssertSmartISAValid() );
//
// 'Smart ISA': no-op
//
return; }
//
// Out-Proc: release ptr
//
// NOTE the ptr is either our cached 'IIS ptr' (if we are on
// mainline thread) or the one we got from gip-master
// (if we are on another thread).
//
// Either way, we simply release it.
//
DBG_ASSERT( AssertOopValid() );
IF_DEBUG( WAM_REFCOUNTS ) {
DBGPRINTF(( DBG_CONTEXT , "WAM_EXEC_BASE(%08x)::ReleaseIWamRequest ptr %08x\n" , this , pIWamRequest )); }
pIWamRequest->Release(); return;
} // WAM_EXEC_BASE::ReleaseIWamRequest
/*---------------------------------------------------------------------*
WAM_EXEC_BASE::GetInterfaceFromGip
*/ HRESULT WAM_EXEC_BASE::GetInterfaceFromGip( IWamRequest ** ppIWamRequest ) {
HRESULT hrRet = NOERROR;
if ( m_gipIWamRequest == 0 ) {
//
// In low-memory, etc cases we may not have a gip cookie
// (see bug 86872)
//
// We quote verbatim from raid:
//
/*
this was the bug: - the call from WAM::ProcessRequest to InitWamExecInfo fails due to oom when calling GetCoreState (probably due to the allocation in the COM marshaler) - thus, _gipIWamRequest remains 0 - we jump to failure code in WAM::ProcessRequest and call WAM_EXEC_INFO:: PrepCleanupAndRelease - PrepCleanupAndRelease assert-failed because _gipIWamRequest == 0 - after the asertion fialure we crash trying to call PrepCleanupWamRequest on a null ptr
this is the fix: - in WAM_EXEC_INFO::PrepCleanupAndRelease we no longer assert, and now proactively avoid the cross-process call if _gipIWamRequest == 0
additional robust-ification, related to the fix: - added fail-fast code to GetIWamRequest for the case _gipIWamRequest == 0 ( replaces the assert stanley saw, above) - many more DBGPRINTFs in InitWamExecInfo and elsewhere */
hrRet = E_FAIL;
} else {
DBG_ASSERT( AssertOopValid() );
IF_DEBUG( WAM_THREADID ) {
DBGPRINTF(( DBG_CONTEXT , "WAM_EXEC_BASE(%08x)::GetInterfaceFromGip before gip.Get" "m_dwThreadIdISA(%d)" "\n" , this , m_dwThreadIdISA ));
}
//
// Get a thread-valid ptr from gip-master
//
hrRet = g_GIPAPI.Get( m_gipIWamRequest , IID_IWamRequest , (void **) ppIWamRequest );
IF_DEBUG( WAM_THREADID ) {
DBGPRINTF(( DBG_CONTEXT , "WAM_EXEC_BASE(%08x)::GetInterfaceFromGip after gip.Get " "m_dwThreadIdISA(%d)" "\n" , this , m_dwThreadIdISA ));
if ( m_dwThreadIdISA == 0 ) {
m_dwThreadIdISA = GetCurrentThreadId();
DBGPRINTF(( DBG_CONTEXT , "WAM_EXEC_BASE(%08x)::GetInterfaceFromGip " "after hokey debug refresh " "m_dwThreadIdISA(%d)" "\n" , this , m_dwThreadIdISA ));
}
}
IF_DEBUG( WAM_THREADID ) {
DBGPRINTF(( DBG_CONTEXT , "WAM_EXEC_BASE(%08x)::GetInterfaceFromGip after CoUninitialize " "m_dwThreadIdISA(%d)" "\n" , this , m_dwThreadIdISA )); }
IF_DEBUG( WAM_REFCOUNTS ) { if ( hrRet == NOERROR ) {
DBGPRINTF(( DBG_CONTEXT , "WAM_EXEC_BASE(%08x)::GetIWamRequest" "gets ptr %08x" "\n" , this , *ppIWamRequest ));
} else {
DBGPRINTF(( DBG_CONTEXT , "WAM_EXEC_BASE(%08x)::GetIWamRequest failed " "hrRet(%08x) " "\n" , this , hrRet ));
} }
}
return hrRet;
}
BOOL WAM_EXEC_BASE::AssertSmartISAValid() {
IF_DEBUG( WAM_THREADID ) {
DBGPRINTF(( DBG_CONTEXT , "WAM_EXEC_BASE(%08x)::AssertSmartISAValid" "\n\t" "m_fInProcess(%d) " "m_pIWamReqInproc(%d) " "m_gipIWamRequest(%d) " "m_pIWamReqSmartISA(%d) " "\n\t" "m_dwThreadIdISA(%d) " "Current thread id(%d) " "\n" , this , m_fInProcess , m_pIWamReqInproc , m_gipIWamRequest , m_pIWamReqSmartISA , m_dwThreadIdISA , GetCurrentThreadId() ));
}
return( AssertOopValid() && m_pIWamReqSmartISA && m_dwThreadIdISA ); }
/************************ End of File *********************************/
|