/*++ Copyright (c) 1999-2000 Microsoft Corporation Module Name: wam_process.hxx Abstract: WAM process management for ISAPI Author: Wade Hilmo (wadeh) 10-Oct-2000 Revision History: --*/ #ifndef _WAM_PROCESS_HXX_ #define _WAM_PROCESS_HXX_ #include "precomp.hxx" #include #include "isapi_request.hxx" #include "iwam.h" #include #define POOL_WAM_CLSID L"{99169CB1-A707-11d0-989D-00C04FD919C1}" #define DEFAULT_RECOVER_LIMIT 5 #define MAX_MESSAGE_TEXT 2048 class ISAPI_REQUEST; class WAM_PROCESS_MANAGER; class WAM_CRASH_RECORD { public: WCHAR szClsid[SIZE_CLSID_STRING]; DWORD dwNumCrashes; LIST_ENTRY leCrashHistory; WAM_CRASH_RECORD() : dwNumCrashes( 0 ) { InitializeListHead( &leCrashHistory ); } }; class WAM_PROCESS { public: WAM_PROCESS( LPCWSTR szWamClsid, WAM_PROCESS_MANAGER * pWamProcessManager, LPCSTR szIsapiHandlerInstance ); HRESULT WAM_PROCESS::Create( LPCWSTR szApplMdPathW ); LONG AddRef() { return InterlockedIncrement( &_cRefs ); } LONG Release() { LONG lRet; lRet = InterlockedDecrement( &_cRefs ); if ( lRet == 0 ) { delete this; } return lRet; } HRESULT ProcessRequest( ISAPI_REQUEST * pIsapiRequest, ISAPI_CORE_DATA * pIsapiCoreData, DWORD * pdwHseResult ); HRESULT ProcessCompletion( ISAPI_REQUEST * pIsapiRequest, DWORD64 IsapiContext, DWORD cbCompletion, DWORD dwCompletionStatus ); VOID DecrementRequestCount( VOID ); VOID HandleCrash( VOID ); HRESULT Disable( BOOL fRemoveFromProcessHash = TRUE ); HRESULT CleanupRequests( DWORD dwDrainTime ); HRESULT Shutdown( VOID ); HRESULT Unload( DWORD dwDrainTime ); LPCWSTR QueryClsid( VOID ) const { return _szWamClsid; } HANDLE QueryProcess( VOID ) { return _hProcess; } BOOL QueryCrashed( VOID ) { return _fCrashed; } HRESULT MarshalAsyncReadBuffer( DWORD64 pWamExecInfo, LPBYTE pBuffer, DWORD cbBuffer ) { return _pIWam->WamMarshalAsyncReadBuffer( pWamExecInfo, pBuffer, cbBuffer ); } VOID AddIsapiRequestToList( ISAPI_REQUEST * pIsapiRequest ); VOID RemoveIsapiRequestFromList( ISAPI_REQUEST * pIsapiRequest ); LIST_ENTRY _leProcess; private: VOID LockRequestList() { EnterCriticalSection( &_csRequestList ); } VOID UnlockRequestList() { LeaveCriticalSection( &_csRequestList ); } VOID DisconnectIsapiRequests( VOID ); ~WAM_PROCESS(); WCHAR _szWamClsid[SIZE_CLSID_STRING]; CHAR _szIsapiHandlerInstance[SIZE_CLSID_STRING]; LONG _cRefs; LONG _cCurrentRequests; LONG _cTotalRequests; LONG _cMaxRequests; IWam * _pIWam; LIST_ENTRY _RequestListHead; CRITICAL_SECTION _csRequestList; WAM_PROCESS_MANAGER * _pWamProcessManager; DWORD _dwProcessId; BSTR _bstrInstanceId; HANDLE _hProcess; LONG _fGoingAway; STRU _strApplMdPathW; BOOL _fCrashed; }; class WAM_PROCESS_HASH : public CTypedHashTable< WAM_PROCESS_HASH, WAM_PROCESS, LPCWSTR > { public: WAM_PROCESS_HASH() : CTypedHashTable< WAM_PROCESS_HASH, WAM_PROCESS, LPCWSTR > ( "WAM_PROCESS_HASH" ) { } static LPCWSTR ExtractKey( const WAM_PROCESS * pWamProcess ) { return pWamProcess->QueryClsid(); } static DWORD CalcKeyHash( LPCWSTR szKey ) { int cchKey = (int)wcslen( szKey ); return HashStringNoCase( szKey, cchKey ); } static bool EqualKeys( LPCWSTR szKey1, LPCWSTR szKey2 ) { return _wcsicmp( szKey1, szKey2 ) == 0; } static void AddRefRecord( WAM_PROCESS * pEntry, int nIncr ) { if ( nIncr == +1 ) { pEntry->AddRef(); } else if ( nIncr == -1 ) { pEntry->Release(); } } private: // // Avoid c++ errors // WAM_PROCESS_HASH( const WAM_PROCESS_HASH & ) : CTypedHashTable< WAM_PROCESS_HASH, WAM_PROCESS, LPCWSTR > ( "WAM_PROCESS_HASH" ) { } WAM_PROCESS_HASH & operator = ( const WAM_PROCESS_HASH & ) { return *this; } }; class WAM_APP_INFO { public: WAM_APP_INFO( LPWSTR szAppPath, LPWSTR szClsid, DWORD dwAppIsolated ) : _cRefs( 1 ), _dwAppIsolated( dwAppIsolated ) { wcsncpy( _szAppPath, szAppPath, MAX_PATH ); wcsncpy( _szClsid, szClsid, SIZE_CLSID_STRING ); } VOID AddRef( VOID ) { InterlockedIncrement( &_cRefs ); } VOID Release( VOID ) { LONG cRefs; cRefs = InterlockedDecrement( &_cRefs ); if ( cRefs == 0 ) { delete this; } } DWORD _dwAppIsolated; WCHAR _szClsid[SIZE_CLSID_STRING]; WCHAR _szAppPath[MAX_PATH]; DWORD _dwAppOopRecoverLimit; private: LONG _cRefs; }; class WAM_PROCESS_MANAGER { public: WAM_PROCESS_MANAGER( LPWSTR szIsapiModule ) : _cRefs( 1 ), _pCatalog( NULL ) { DBG_ASSERT( szIsapiModule ); INITIALIZE_CRITICAL_SECTION( &_csWamHashLock ); INITIALIZE_CRITICAL_SECTION( &_csCrashHistoryLock ); InitializeListHead( &_CrashHistoryList ); wcsncpy( _szIsapiModule, szIsapiModule, MAX_PATH ); } HRESULT WAM_PROCESS_MANAGER::Create( VOID ); HRESULT GetWamProcess( LPCWSTR szWamClsid, LPCWSTR szApplMdPathW, DWORD * pdwWamSubError, WAM_PROCESS ** ppWamProcess, LPCSTR szIsapiHandlerInstance ); HRESULT GetWamProcessInfo( LPCWSTR szAppPath, WAM_APP_INFO ** ppWamAppInfo, BOOL * pfIsLoaded ); HRESULT RemoveWamProcessFromHash( WAM_PROCESS * pWamProcess ); static LK_PREDICATE UnloadWamProcess( WAM_PROCESS * pWamProcess, void * pvState ); HRESULT Shutdown( VOID ); ICOMAdminCatalog2 * QueryCatalog( VOID ) { return _pCatalog; } VOID LockWamProcessHash() { EnterCriticalSection( &_csWamHashLock ); } VOID UnlockWamProcessHash() { LeaveCriticalSection( &_csWamHashLock ); } LONG AddRef() { return InterlockedIncrement( &_cRefs ); } LONG Release() { LONG cRefs = InterlockedDecrement( &_cRefs ); if ( cRefs == 0 ) { delete this; return 0; } return cRefs; } LPWSTR QueryIsapiModule( VOID ) { DBG_ASSERT( _szIsapiModule[0] != L'\0' ); return _szIsapiModule; } VOID RegisterCrash( LPCWSTR szWamClsid ); HRESULT QueryCrashHistory( LPCWSTR szWamClsid, DWORD * pdwNumCrashes ); private: // // Avoid c++ errors // WAM_PROCESS_MANAGER( const WAM_PROCESS_MANAGER & ) {} WAM_PROCESS_MANAGER & operator = ( const WAM_PROCESS_MANAGER & ) { return *this; } ~WAM_PROCESS_MANAGER() { LIST_ENTRY * pleTemp; WAM_CRASH_RECORD * pWamCrashRecord; // // Delete the WAM crash history. It's not necessary // to lock the list because if WAM_PROCESS_MANAGER is // getting destroyed, then there had better not be // any requests alive that are holding references // to the entries. // while ( !IsListEmpty( &_CrashHistoryList ) ) { pleTemp = RemoveHeadList( &_CrashHistoryList ); pWamCrashRecord = CONTAINING_RECORD( pleTemp, WAM_CRASH_RECORD, leCrashHistory ); DBG_ASSERT( pWamCrashRecord ); delete pWamCrashRecord; pWamCrashRecord = NULL; } // // Release the COM catalog // if ( _pCatalog ) { _pCatalog->Release(); } // // Cleanup the hash lock (the hash itself will // get cleaned up automatically). // DeleteCriticalSection( &_csWamHashLock ); DeleteCriticalSection( &_csCrashHistoryLock ); IF_DEBUG( ISAPI ) { DBGPRINTF(( DBG_CONTEXT, "WAM_PROCESS_MANAGER %p has been destroyed.\r\n", this )); } } VOID LockCrashHistoryList( VOID ) { EnterCriticalSection( &_csCrashHistoryLock ); } VOID UnlockCrashHistoryList( VOID ) { LeaveCriticalSection( &_csCrashHistoryLock ); } WAM_PROCESS_HASH _WamProcessHash; CRITICAL_SECTION _csWamHashLock; CRITICAL_SECTION _csCrashHistoryLock; ICOMAdminCatalog2 * _pCatalog; LONG _cRefs; WCHAR _szIsapiModule[MAX_PATH]; LIST_ENTRY _CrashHistoryList; }; #endif // _WAM_PROCESS_HXX