diff --git a/src/AspNetCoreModuleV2/CommonLib/iapplication.h b/src/AspNetCoreModuleV2/CommonLib/iapplication.h index 590fd7e51a..ef5d2bf8d7 100644 --- a/src/AspNetCoreModuleV2/CommonLib/iapplication.h +++ b/src/AspNetCoreModuleV2/CommonLib/iapplication.h @@ -3,6 +3,7 @@ #pragma once +#include #include "irequesthandler.h" enum APPLICATION_STATUS @@ -54,3 +55,18 @@ public: _In_ IHttpContext *pHttpContext, _Out_ IREQUEST_HANDLER **pRequestHandler) = 0; }; + +struct IAPPLICATION_DELETER +{ + void operator ()(IAPPLICATION* application) const + { + application->DereferenceApplication(); + } +}; + +template< class APPLICATION > +std::unique_ptr ReferenceApplication(APPLICATION* application) +{ + application->ReferenceApplication(); + return std::unique_ptr(application); +}; diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp index 7714d9a9e4..693ce28068 100644 --- a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp @@ -208,98 +208,11 @@ IN_PROCESS_APPLICATION::ShutDownInternal() s_Application = NULL; } -REQUEST_NOTIFICATION_STATUS -IN_PROCESS_APPLICATION::OnAsyncCompletion( - DWORD cbCompletion, - HRESULT hrCompletionStatus, - IN_PROCESS_HANDLER* pInProcessHandler -) -{ - REQUEST_NOTIFICATION_STATUS dwRequestNotificationStatus = RQ_NOTIFICATION_CONTINUE; - - ReferenceApplication(); - - if (pInProcessHandler->QueryIsManagedRequestComplete()) - { - // means PostCompletion has been called and this is the associated callback. - dwRequestNotificationStatus = pInProcessHandler->QueryAsyncCompletionStatus(); - } - else if (m_fBlockCallbacksIntoManaged) - { - // this can potentially happen in ungraceful shutdown. - // Or something really wrong happening with async completions - // At this point, managed is in a shutting down state and we cannot send a request to it. - pInProcessHandler->QueryHttpContext()->GetResponse()->SetStatus(503, - "Server has been shutdown", - 0, - (ULONG)HRESULT_FROM_WIN32(ERROR_SHUTDOWN_IN_PROGRESS)); - dwRequestNotificationStatus = RQ_NOTIFICATION_FINISH_REQUEST; - } - else - { - // Call the managed handler for async completion. - dwRequestNotificationStatus = m_AsyncCompletionHandler(pInProcessHandler->QueryManagedHttpContext(), hrCompletionStatus, cbCompletion); - } - - DereferenceApplication(); - - return dwRequestNotificationStatus; -} - -REQUEST_NOTIFICATION_STATUS -IN_PROCESS_APPLICATION::OnExecuteRequest( - _In_ IHttpContext* pHttpContext, - _In_ IN_PROCESS_HANDLER* pInProcessHandler -) -{ - REQUEST_NOTIFICATION_STATUS dwRequestNotificationStatus = RQ_NOTIFICATION_CONTINUE; - PFN_REQUEST_HANDLER pRequestHandler = NULL; - - ReferenceApplication(); - pRequestHandler = m_RequestHandler; - - if (pRequestHandler == NULL) - { - // - // return error as the application did not register callback - // - if (ANCMEvents::ANCM_EXECUTE_REQUEST_FAIL::IsEnabled(pHttpContext->GetTraceContext())) - { - ANCMEvents::ANCM_EXECUTE_REQUEST_FAIL::RaiseEvent(pHttpContext->GetTraceContext(), - NULL, - (ULONG)E_APPLICATION_ACTIVATION_EXEC_FAILURE); - } - - pHttpContext->GetResponse()->SetStatus(500, - "Internal Server Error", - 0, - (ULONG)E_APPLICATION_ACTIVATION_EXEC_FAILURE); - - dwRequestNotificationStatus = RQ_NOTIFICATION_FINISH_REQUEST; - } - else if (m_status != APPLICATION_STATUS::RUNNING || m_fBlockCallbacksIntoManaged) - { - pHttpContext->GetResponse()->SetStatus(503, - "Server is currently shutting down.", - 0, - (ULONG)HRESULT_FROM_WIN32(ERROR_SHUTDOWN_IN_PROGRESS)); - dwRequestNotificationStatus = RQ_NOTIFICATION_FINISH_REQUEST; - } - else - { - dwRequestNotificationStatus = pRequestHandler(pInProcessHandler, m_RequestHandlerContext); - } - - DereferenceApplication(); - - return dwRequestNotificationStatus; -} - VOID IN_PROCESS_APPLICATION::SetCallbackHandles( _In_ PFN_REQUEST_HANDLER request_handler, _In_ PFN_SHUTDOWN_HANDLER shutdown_handler, - _In_ PFN_MANAGED_CONTEXT_HANDLER async_completion_handler, + _In_ PFN_ASYNC_COMPLETION_HANDLER async_completion_handler, _In_ VOID* pvRequstHandlerContext, _In_ VOID* pvShutdownHandlerContext ) @@ -673,7 +586,7 @@ IN_PROCESS_APPLICATION::CreateHandler( HRESULT hr = S_OK; IREQUEST_HANDLER* pHandler = NULL; - pHandler = new IN_PROCESS_HANDLER(pHttpContext, this); + pHandler = new IN_PROCESS_HANDLER(::ReferenceApplication(this), pHttpContext, m_RequestHandler, m_RequestHandlerContext, m_AsyncCompletionHandler); if (pHandler == NULL) { diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.h b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.h index 0bcd1cbd48..1f6e3da570 100644 --- a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.h +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.h @@ -4,13 +4,13 @@ #pragma once #include "InProcessApplicationBase.h" -#include "inprocesshandler.h" #include "requesthandler_config.h" #include "IOutputManager.h" +class IN_PROCESS_HANDLER; typedef REQUEST_NOTIFICATION_STATUS(WINAPI * PFN_REQUEST_HANDLER) (IN_PROCESS_HANDLER* pInProcessHandler, void* pvRequestHandlerContext); typedef BOOL(WINAPI * PFN_SHUTDOWN_HANDLER) (void* pvShutdownHandlerContext); -typedef REQUEST_NOTIFICATION_STATUS(WINAPI * PFN_MANAGED_CONTEXT_HANDLER)(void *pvManagedHttpContext, HRESULT hrCompletionStatus, DWORD cbCompletion); +typedef REQUEST_NOTIFICATION_STATUS(WINAPI * PFN_ASYNC_COMPLETION_HANDLER)(void *pvManagedHttpContext, HRESULT hrCompletionStatus, DWORD cbCompletion); class IN_PROCESS_APPLICATION : public InProcessApplicationBase { @@ -32,7 +32,7 @@ public: SetCallbackHandles( _In_ PFN_REQUEST_HANDLER request_callback, _In_ PFN_SHUTDOWN_HANDLER shutdown_callback, - _In_ PFN_MANAGED_CONTEXT_HANDLER managed_context_callback, + _In_ PFN_ASYNC_COMPLETION_HANDLER managed_context_callback, _In_ VOID* pvRequstHandlerContext, _In_ VOID* pvShutdownHandlerContext ); @@ -60,20 +60,6 @@ public: HRESULT hr ); - REQUEST_NOTIFICATION_STATUS - OnAsyncCompletion( - DWORD cbCompletion, - HRESULT hrCompletionStatus, - IN_PROCESS_HANDLER* pInProcessHandler - ); - - REQUEST_NOTIFICATION_STATUS - OnExecuteRequest - ( - IHttpContext* pHttpContext, - IN_PROCESS_HANDLER* pInProcessHandler - ); - VOID StopCallsIntoManaged( VOID @@ -117,6 +103,12 @@ public: return m_pConfig.get(); } + bool + QueryBlockCallbacksIntoManaged() const + { + return m_fBlockCallbacksIntoManaged; + } + private: IHttpServer & m_pHttpServer; @@ -132,7 +124,7 @@ private: PFN_SHUTDOWN_HANDLER m_ShutdownHandler; VOID* m_ShutdownHandlerContext; - PFN_MANAGED_CONTEXT_HANDLER m_AsyncCompletionHandler; + PFN_ASYNC_COMPLETION_HANDLER m_AsyncCompletionHandler; // The event that gets triggered when managed initialization is complete HANDLE m_pInitalizeEvent; diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.cpp b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.cpp index 1494eb158e..d658fa957b 100644 --- a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.cpp +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.cpp @@ -10,20 +10,22 @@ ALLOC_CACHE_HANDLER * IN_PROCESS_HANDLER::sm_pAlloc = NULL; IN_PROCESS_HANDLER::IN_PROCESS_HANDLER( + _In_ std::unique_ptr pApplication, _In_ IHttpContext *pW3Context, - _In_ IN_PROCESS_APPLICATION *pApplication -): m_pW3Context(pW3Context), - m_requestNotificationStatus(RQ_NOTIFICATION_PENDING), - m_pApplication(pApplication), - m_fManagedRequestComplete(FALSE) + _In_ PFN_REQUEST_HANDLER pRequestHandler, + _In_ void * pRequestHandlerContext, + _In_ PFN_ASYNC_COMPLETION_HANDLER pAsyncCompletion +): m_pManagedHttpContext(nullptr), + m_requestNotificationStatus(RQ_NOTIFICATION_PENDING), + m_fManagedRequestComplete(FALSE), + m_pW3Context(pW3Context), + m_pApplication(std::move(pApplication)), + m_pRequestHandler(pRequestHandler), + m_pRequestHandlerContext(pRequestHandlerContext), + m_pAsyncCompletionHandler(pAsyncCompletion) { } -IN_PROCESS_HANDLER::~IN_PROCESS_HANDLER() -{ - //todo -} - __override REQUEST_NOTIFICATION_STATUS IN_PROCESS_HANDLER::OnExecuteRequestHandler() @@ -38,8 +40,32 @@ IN_PROCESS_HANDLER::OnExecuteRequestHandler() L"InProcess Application"); } - //SetHttpSysDisconnectCallback(); - return m_pApplication->OnExecuteRequest(m_pW3Context, this); + if (m_pRequestHandler == NULL) + { + // + // return error as the application did not register callback + // + if (ANCMEvents::ANCM_EXECUTE_REQUEST_FAIL::IsEnabled(m_pW3Context->GetTraceContext())) + { + ANCMEvents::ANCM_EXECUTE_REQUEST_FAIL::RaiseEvent(m_pW3Context->GetTraceContext(), + NULL, + (ULONG)E_APPLICATION_ACTIVATION_EXEC_FAILURE); + } + + m_pW3Context->GetResponse()->SetStatus(500, + "Internal Server Error", + 0, + (ULONG)E_APPLICATION_ACTIVATION_EXEC_FAILURE); + + return RQ_NOTIFICATION_FINISH_REQUEST; + } + else if (m_pApplication->QueryStatus() != APPLICATION_STATUS::RUNNING || m_pApplication-> + QueryBlockCallbacksIntoManaged()) + { + return ServerShutdownMessage(); + } + + return m_pRequestHandler(this, m_pRequestHandlerContext); } __override @@ -49,9 +75,28 @@ IN_PROCESS_HANDLER::OnAsyncCompletion( HRESULT hrCompletionStatus ) { - // OnAsyncCompletion must call into the application if there was a error. We will redo calls - // to Read/Write if we called cancelIo on the IHttpContext. - return m_pApplication->OnAsyncCompletion(cbCompletion, hrCompletionStatus, this); + if (m_fManagedRequestComplete) + { + // means PostCompletion has been called and this is the associated callback. + return m_requestNotificationStatus; + } + if (m_pApplication->QueryBlockCallbacksIntoManaged()) + { + // this can potentially happen in ungraceful shutdown. + // Or something really wrong happening with async completions + // At this point, managed is in a shutting down state and we cannot send a request to it. + return ServerShutdownMessage(); + } + + // Call the managed handler for async completion. + return m_pAsyncCompletionHandler(m_pManagedHttpContext, hrCompletionStatus, cbCompletion); +} + +REQUEST_NOTIFICATION_STATUS IN_PROCESS_HANDLER::ServerShutdownMessage() const +{ + m_pW3Context->GetResponse()->SetStatus(503, "Server has been shutdown", 0, + (ULONG)HRESULT_FROM_WIN32(ERROR_SHUTDOWN_IN_PROGRESS)); + return RQ_NOTIFICATION_FINISH_REQUEST; } VOID @@ -60,31 +105,6 @@ IN_PROCESS_HANDLER::TerminateRequest( ) { UNREFERENCED_PARAMETER(fClientInitiated); - //todo -} - -PVOID -IN_PROCESS_HANDLER::QueryManagedHttpContext( - VOID -) -{ - return m_pManagedHttpContext; -} - -BOOL -IN_PROCESS_HANDLER::QueryIsManagedRequestComplete( - VOID -) -{ - return m_fManagedRequestComplete; -} - -IHttpContext* -IN_PROCESS_HANDLER::QueryHttpContext( - VOID -) -{ - return m_pW3Context; } VOID @@ -95,14 +115,6 @@ IN_PROCESS_HANDLER::IndicateManagedRequestComplete( m_fManagedRequestComplete = TRUE; } -REQUEST_NOTIFICATION_STATUS -IN_PROCESS_HANDLER::QueryAsyncCompletionStatus( - VOID -) -{ - return m_requestNotificationStatus; -} - VOID IN_PROCESS_HANDLER::SetAsyncCompletionStatus( REQUEST_NOTIFICATION_STATUS requestNotificationStatus @@ -165,7 +177,7 @@ HRESULT } hr = sm_pAlloc->Initialize(sizeof(IN_PROCESS_HANDLER), - 64); // nThreshold + 64); // nThreshold Finished: if (FAILED(hr)) diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.h b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.h index a9c068a751..3934e2cd92 100644 --- a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.h +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocesshandler.h @@ -3,7 +3,11 @@ #pragma once +#include "precomp.hxx" #include "requesthandler.h" +#include +#include "iapplication.h" +#include "inprocessapplication.h" class IN_PROCESS_APPLICATION; @@ -11,10 +15,13 @@ class IN_PROCESS_HANDLER : public REQUEST_HANDLER { public: IN_PROCESS_HANDLER( + _In_ std::unique_ptr pApplication, _In_ IHttpContext *pW3Context, - _In_ IN_PROCESS_APPLICATION *pApplication); + _In_ PFN_REQUEST_HANDLER pRequestHandler, + _In_ void * pRequestHandlerContext, + _In_ PFN_ASYNC_COMPLETION_HANDLER pAsyncCompletion); - ~IN_PROCESS_HANDLER() override; + ~IN_PROCESS_HANDLER() override = default; __override REQUEST_NOTIFICATION_STATUS @@ -32,37 +39,25 @@ public: TerminateRequest( bool fClientInitiated ) override; - - PVOID - QueryManagedHttpContext( + + IHttpContext* + QueryHttpContext( VOID - ); + ) const + { + return m_pW3Context; + } VOID SetManagedHttpContext( PVOID pManagedHttpContext ); - IHttpContext* - QueryHttpContext( - VOID - ); - - BOOL - QueryIsManagedRequestComplete( - VOID - ); - VOID IndicateManagedRequestComplete( VOID ); - REQUEST_NOTIFICATION_STATUS - QueryAsyncCompletionStatus( - VOID - ); - VOID SetAsyncCompletionStatus( REQUEST_NOTIFICATION_STATUS requestNotificationStatus @@ -76,12 +71,18 @@ public: HRESULT StaticInitialize(VOID); - private: + REQUEST_NOTIFICATION_STATUS + ServerShutdownMessage() const; + PVOID m_pManagedHttpContext; BOOL m_fManagedRequestComplete; REQUEST_NOTIFICATION_STATUS m_requestNotificationStatus; IHttpContext* m_pW3Context; - IN_PROCESS_APPLICATION* m_pApplication; + std::unique_ptr m_pApplication; + PFN_REQUEST_HANDLER m_pRequestHandler; + void* m_pRequestHandlerContext; + PFN_ASYNC_COMPLETION_HANDLER m_pAsyncCompletionHandler; + static ALLOC_CACHE_HANDLER * sm_pAlloc; }; diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cxx b/src/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cxx index c4860c1acb..1f1590ae75 100644 --- a/src/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cxx +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cxx @@ -14,7 +14,7 @@ register_callbacks( _In_ IN_PROCESS_APPLICATION* pInProcessApplication, _In_ PFN_REQUEST_HANDLER request_handler, _In_ PFN_SHUTDOWN_HANDLER shutdown_handler, - _In_ PFN_MANAGED_CONTEXT_HANDLER async_completion_handler, + _In_ PFN_ASYNC_COMPLETION_HANDLER async_completion_handler, _In_ VOID* pvRequstHandlerContext, _In_ VOID* pvShutdownHandlerContext )