// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. #pragma once #include #include "InProcessApplicationBase.h" #include "InProcessOptions.h" #include "BaseOutputManager.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_ASYNC_COMPLETION_HANDLER)(void *pvManagedHttpContext, HRESULT hrCompletionStatus, DWORD cbCompletion); class IN_PROCESS_APPLICATION : public InProcessApplicationBase { public: IN_PROCESS_APPLICATION( IHttpServer& pHttpServer, IHttpApplication& pApplication, std::unique_ptr pConfig, APPLICATION_PARAMETER *pParameters, DWORD nParameters); ~IN_PROCESS_APPLICATION(); __override VOID StopInternal(bool fServerInitiated) override; VOID SetCallbackHandles( _In_ PFN_REQUEST_HANDLER request_callback, _In_ PFN_SHUTDOWN_HANDLER shutdown_callback, _In_ PFN_ASYNC_COMPLETION_HANDLER managed_context_callback, _In_ VOID* pvRequstHandlerContext, _In_ VOID* pvShutdownHandlerContext ); __override HRESULT CreateHandler( _In_ IHttpContext *pHttpContext, _Out_ IREQUEST_HANDLER **pRequestHandler) override; // Executes the .NET Core process void ExecuteApplication(); HRESULT LoadManagedApplication(); void QueueStop(); void StopIncomingRequests() { QueueStop(); } void StopCallsIntoManaged() { m_blockManagedCallbacks = true; } static VOID SetMainCallback(hostfxr_main_fn mainCallback) { s_fMainCallback = mainCallback; } static IN_PROCESS_APPLICATION* GetInstance() { return s_Application; } const std::wstring& QueryExeLocation() const { return m_dotnetExeKnownLocation; } const InProcessOptions& QueryConfig() const { return *m_pConfig; } bool QueryBlockCallbacksIntoManaged() const { return m_blockManagedCallbacks; } static HRESULT Start( IHttpServer& pServer, IHttpApplication& pHttpApplication, APPLICATION_PARAMETER* pParameters, DWORD nParameters, std::unique_ptr& application); private: struct ExecuteClrContext: std::enable_shared_from_this { ExecuteClrContext(): m_argc(0), m_pProc(nullptr), m_exitCode(0), m_exceptionCode(0) { } DWORD m_argc; std::unique_ptr m_argv; hostfxr_main_fn m_pProc; int m_exitCode; int m_exceptionCode; }; // Thread executing the .NET Core process this might be abandoned in timeout cases std::thread m_clrThread; // Thread tracking the CLR thread, this one is always joined on shutdown std::thread m_workerThread; // The event that gets triggered when managed initialization is complete HandleWrapper m_pInitializeEvent; // The event that gets triggered when worker thread should exit HandleWrapper m_pShutdownEvent; // The request handler callback from managed code PFN_REQUEST_HANDLER m_RequestHandler; VOID* m_RequestHandlerContext; // The shutdown handler callback from managed code PFN_SHUTDOWN_HANDLER m_ShutdownHandler; VOID* m_ShutdownHandlerContext; PFN_ASYNC_COMPLETION_HANDLER m_AsyncCompletionHandler; std::wstring m_dotnetExeKnownLocation; std::atomic_bool m_blockManagedCallbacks; bool m_Initialized; bool m_waitForShutdown; std::unique_ptr m_pConfig; static IN_PROCESS_APPLICATION* s_Application; std::unique_ptr m_pLoggerProvider; inline static const LPCSTR s_exeLocationParameterName = "InProcessExeLocation"; VOID UnexpectedThreadExit(const ExecuteClrContext& context) const; HRESULT SetEnvironmentVariablesOnWorkerProcess(); void StopClr(); static void ClrThreadEntryPoint(const std::shared_ptr &context); static void ExecuteClr(const std::shared_ptr &context); // Allows to override call to hostfxr_main with custom callback // used in testing inline static hostfxr_main_fn s_fMainCallback = nullptr; };