////////////////////////////////////////////////////////////////////////////////////////
// File: AxeHosting.h
//
// Abstract: This file contains definitions that are consumed by AXE Hosting applications.
//
// (c) Microsoft. All rights reserved.
////////////////////////////////////////////////////////////////////////////////////////


#if defined( _MSC_VER )
#pragma once
#endif  // _MSC_VER

#if !defined( AXEHOSTING_H )
#define AXEHOSTING_H

#if NTDDI_VERSION >= NTDDI_WIN7

// This file is only for C++ clients. C is not supported.
//
#if !defined( __cplusplus )
#error C++ compiler required
#endif // C++


////////////////////////////////////////////////////////////////////////////////////////
// Include files
////////////////////////////////////////////////////////////////////////////////////////

#include "AxeCore.h"


////////////////////////////////////////////////////////////////////////////////////////
// Forward declarations (global namespace)
////////////////////////////////////////////////////////////////////////////////////////

struct _EVENT_RECORD; // #include <evntcons.h>


// The AXE Solution APIs exist in the Microsoft::Assessments::Hosting namespace.
//
namespace Microsoft { namespace Assessments { namespace Hosting
{
    ////////////////////////////////////////////////////////////////////////////////////////
    // Constants
    ////////////////////////////////////////////////////////////////////////////////////////

    static const size_t RESULTS_MAX_FILENAME = 65;


    ////////////////////////////////////////////////////////////////////////////////////////
    // Forward declarations
    ////////////////////////////////////////////////////////////////////////////////////////

    struct Solution;
    struct Engine;
    struct Job;
    struct Assessment;
    struct JobResults;
    struct AssessmentResultsCollection;
    struct AssessmentResults;


    ////////////////////////////////////////////////////////////////////////////////////////
    // Type defines
    ////////////////////////////////////////////////////////////////////////////////////////


    ////////////////////////////////////////////////////////////////////////////////////////
    // Enumerations
    ////////////////////////////////////////////////////////////////////////////////////////

    enum SolutionFlags
    {
        SolutionFlagNone                            = 0,
        SolutionFlagWorkloads                       = 0x1 << 31,  // 0x80000000
    };

    namespace JobExecutionFlags { enum JobExecutionFlags
    {
        None                                        = 0,
        ExecuteAsync                                = 0x1 << 0,  // 0x00000001
    }; }

    namespace AnalyzeResultsFlags { enum AnalyzeResultsFlags
    {
        None                                        = 0,
        ExecuteAsync                                = 0x1 << 0,  // 0x00000001
        PublishToSource                             = 0x1 << 1,  // 0x00000002
    }; }

    enum SolutionError
    {
        SolutionErrorNone                           = 0,
        SolutionErrorAlreadyInit                    = AXE_E_ALREADY_INIT,
        SolutionErrorWorkloadInit                   = AXE_E_WORKLOAD_INIT,
        SolutionErrorInternalError                  = AXE_E_INTERNAL_ERROR,
        SolutionErrorUnknownWin32Error              = AXE_E_UNKNOWN_WIN32_ERROR,
        SolutionErrorBadManifest                    = AXE_E_BAD_MANIFEST,
        SolutionErrorJobRunning                     = AXE_E_JOB_RUNNING,
        SolutionErrorJobNotRunning                  = AXE_E_JOB_NOT_RUNNING,
        SolutionErrorShellExecuteNoProcess          = AXE_E_SHELLEXECUTE_NOPROCESS,
        SolutionErrorQueuedEvents                   = AXE_E_QUEUED_APC_EVENTS,
    };

    enum AssessmentExecutionError
    {
        AssessmentExecutionErrorNone                 = 0,
        AssessmentExecutionErrorCouldNotStart        = AXE_E_ASSESSMENT_COULD_NOT_START,
        AssessmentExecutionErrorCouldNotFinish       = AXE_E_ASSESSMENT_COULD_NOT_FINISH,
        AssessmentExecutionErrorCompletedWithError   = AXE_E_ASSESSMENT_COMPLETED_WITH_ERROR,
        AssessmentExecutionErrorResultsInvalid       = AXE_E_ASSESSMENT_RESULTS_INVALID,
        AssessmentExecutionErrorCanceled             = AXE_E_ASSESSMENT_CANCELED,
        AssessmentExecutionErrorTerminated           = AXE_E_ASSESSMENT_TERMINATED,
        AssessmentExecutionErrorCrashed              = AXE_E_ASSESSMENT_CRASHED,
    };

    enum JobExecutionError
    {
        JobExecutionErrorNone                        = 0,
        JobExecutionErrorCanceled                    = AXE_E_JOB_CANCELED,
        JobExecutionErrorAssessmentsFailed           = AXE_E_JOB_ASSESSMENTS_FAILED,
        JobExecutionErrorAnotherRebootPending        = AXE_E_JOB_ANOTHER_REBOOT_PENDING,
        JobExecutionErrorNoRebootPending             = AXE_E_JOB_NO_REBOOT_PENDING,
        JobExecutionErrorPreparation                 = AXE_E_JOB_PREPARATION,
        JobExecutionErrorResultsFailed               = AXE_E_JOB_RESULTS_FAILED,
        JobExecutionErrorAssessmentPreparation       = AXE_E_JOB_ASSESSMENT_PREPARATION,
        JobExecutionErrorPostExecution               = AXE_E_JOB_POSTEXECUTION,
        JobExecutionErrorWaitTimeout                 = AXE_E_JOB_WAIT_TIMEOUT,
        JobExecutionErrorChanged                     = AXE_E_JOB_CHANGED,
        JobExecutionErrorRestartFailed               = AXE_E_JOB_RESTART_FAILED,
        JobExecutionErrorRestartBadData              = AXE_E_JOB_RESTART_BADDATA,
        JobExecutionErrorSolutionRestart             = AXE_E_JOB_SOLUTION_RESTART,
    };
    
    enum ThreadingModel
    {
        ThreadingModelNone = 0,  // always first
        ThreadingModelFree,
        ThreadingModelAPC,
        ThreadingModelInvalid  // always last
    };

    enum CannotAnalyzeReason
    {
        CannotAnalyzeReasonNone = 0,
        CannotAnalyzeReasonNotSupported,
        CannotAnalyzeReasonExecutionFailed,
        CannotAnalyzeReasonInvalid  // always last
    };

    ////////////////////////////////////////////////////////////////////////////////////////
    // Structures
    ////////////////////////////////////////////////////////////////////////////////////////

    struct SolutionParameters
    {
        DWORD Size;
        DWORD Flags;
        LPCWSTR WorkingDirectory;
    };

    struct JobExecutionInfo
    {
        DWORD Size;
        const Job* Job;
        DWORD Flags;
        DWORD Timeout;
        LPCWSTR RestartDirectory;
        LPCWSTR RestartCommand;
        LPCWSTR RestartMinimumCommand;
        LPCWSTR WorkloadTempDirectory;
        INT WorkloadAssessmentIndex;
        JobExecutionError Error;
        BOOL Restarting;
    };

    struct AnalyzeResultsInfo
    {
        DWORD Size;
        const JobResults* Results;
        DWORD Flags;
        JobExecutionError Error;
        LPCWSTR ResultsPublishPath;
    };

    // OnJobPending event argument structure
    //
    struct JobPendingEventArgs
    {
        DWORD Size;
        const Job* Job;
        DWORD Timeout;
    };

    // OnJobBegin event argument structure
    //
    struct JobBeginEventArgs
    {
        DWORD Size;
        const Job* Job;
    };

    // OnJobRestart event argument structure
    //
    struct JobRestartEventArgs
    {
        DWORD Size;
        const Job* Job;
    };

    // OnJobEnd event argument structure
    //
    struct JobEndEventArgs
    {
        DWORD Size;
        const Job* Job;
        JobExecutionError Error;
        const ErrorList* ErrorList;
        UINT ExecutedAssessmentCount;
        UINT FailedAssessmentCount;
        LPCWSTR ResultPath;
        WCHAR ResultFolder[RESULTS_MAX_FILENAME];
        WCHAR ResultFileName[RESULTS_MAX_FILENAME];
    };

    // OnAssessmentBegin event argument structure
    //
    struct AssessmentBeginEventArgs
    {
        DWORD Size;
        INT AssessmentIndex;
        const Assessment* Assessment;
    };

    // OnAssessmentEnd event argument structure
    //
    struct AssessmentEndEventArgs
    {
        DWORD Size;
        INT AssessmentIndex;
        const Assessment* Assessment;
        AssessmentExecutionError Error;
        const ErrorList* ErrorList;
        INT ExitCode;
    };

    // OnProgressUpdate event argument structure
    //
    struct ProgressUpdateEventArgs
    {
        DWORD Size;
        INT AssessmentIndex;
        const Assessment* Assessment;
        AxeProgressType ProgressType;
        UINT ProgressValue;
        LPCWSTR ProgressMessage;
    };

    // ILogReaderCallback LogReaderCallback data structure.
    //
    struct LogReaderCallbackData
    {
        struct _EVENT_RECORD* EventRecord;
        FILETIME Timestamp;
        LPCWSTR LogDate;
        LPCWSTR LogTime;
        LPCWSTR LogText;
        LPCWSTR LogError;
    };


    ////////////////////////////////////////////////////////////////////////////////////////
    // Event Interfaces/Delegates
    ////////////////////////////////////////////////////////////////////////////////////////

    // JobPending event handler
    //
    struct IJobPendingEventHandler
    {
        virtual void OnJobPending(
            Engine* sender,
            const JobPendingEventArgs* e) = 0;
    };

    // JobBegin event handler
    //
    struct IJobBeginEventHandler
    {
        virtual void OnJobBegin(
            Engine* sender,
            const JobBeginEventArgs* e) = 0;
    };

    // JobRestart event handler
    //
    struct IJobRestartEventHandler
    {
        virtual void OnJobRestart(
            Engine* sender,
            const JobRestartEventArgs* e) = 0;
    };

    // JobEnd event handler
    //
    struct IJobEndEventHandler
    {
        virtual void OnJobEnd(
            Engine* sender,
            const JobEndEventArgs* e) = 0;
    };

    // AssessmentBegin handler
    //
    struct IAssessmentBeginEventHandler
    {
        virtual void OnAssessmentBegin(
            Engine* sender,
            const AssessmentBeginEventArgs* e) = 0;
    };

    // AssessmentEnd event handler
    //
    struct IAssessmentEndEventHandler
    {
        virtual void OnAssessmentEnd(
            Engine* sender,
            const AssessmentEndEventArgs* e) = 0;
    };

    // ProgressUpdate event handler
    //
    struct IProgressUpdateEventHandler
    {
        virtual void OnProgressUpdate(
            Engine* sender,
            const ProgressUpdateEventArgs* e) = 0;
    };

    // Solution ReadLogFile callback.
    //
    struct ILogReaderCallback
    {
        virtual BOOL LogReaderCallback(
            const LogReaderCallbackData* data) = 0;
    };


    ////////////////////////////////////////////////////////////////////////////////////////
    // Interfaces
    ////////////////////////////////////////////////////////////////////////////////////////

    // Solution interface
    //
    struct Solution : public IUnknown
    {
        virtual HRESULT GetErrorText(
            _In_ HRESULT axeError,
            _Deref_out_ ErrorList** errorList) = 0;
        virtual HRESULT CreateEngine(
            _Deref_out_ Engine** engine) = 0;
        virtual HRESULT CreateJob(
            _In_z_ LPCWSTR jobPath,
            _Deref_out_ Job** newJob) = 0;
        virtual HRESULT CreateJob(
            _In_z_ LPCWSTR jobPath,
            _Deref_out_ Job** newJob,
            _Deref_opt_out_opt_ ErrorList** errorList) = 0;
        virtual HRESULT CreateResults(
            _In_z_ LPCWSTR resultPath,
            _Outptr_ JobResults** newResults) = 0;
        virtual HRESULT CreateResults(
            _In_z_ LPCWSTR resultPath,
            _Outptr_ JobResults** newResults,
            _Outptr_result_maybenull_ ErrorList** errorList) = 0;
        virtual HRESULT CreateLogger(
            _Deref_out_ Logging** log) = 0;
        virtual HRESULT ReadLogFile(
            _In_z_ LPCWSTR logPath,
            _In_ ILogReaderCallback* callback) = 0;
        virtual HRESULT GetSessionFolder(
            _Outptr_opt_result_maybenull_z_ LPCWSTR* sessionFolder) const = 0;
        virtual HRESULT GetSessionLogFile(
            _Outptr_opt_result_maybenull_z_ LPCWSTR* sessionLogFile) const = 0;
        virtual ~Solution(){}
    };

    // Engine interface
    //
    struct Engine : public IUnknown
    {
        virtual HRESULT GetEventThreadingModel(
            _Out_ ThreadingModel* eventThreadingModel) = 0;
        virtual HRESULT SetEventThreadingModel(
            _In_ ThreadingModel eventThreadingModel) = 0;
        virtual HRESULT SetJobPending(
            _In_opt_ IJobPendingEventHandler* jobPending) = 0;
        virtual HRESULT SetJobBegin(
            _In_opt_ IJobBeginEventHandler* jobBegin) = 0;
        virtual HRESULT SetJobRestart(
            _In_opt_ IJobRestartEventHandler* jobRestart) = 0;
        virtual HRESULT SetJobEnd(
            _In_opt_ IJobEndEventHandler* jobEnd) = 0;
        virtual HRESULT SetAssessmentBegin(
            _In_opt_ IAssessmentBeginEventHandler* assessmentBegin) = 0;
        virtual HRESULT SetAssessmentEnd(
            _In_opt_ IAssessmentEndEventHandler* assessmentEnd) = 0;
        virtual HRESULT SetProgressUpdate(
            _In_opt_ IProgressUpdateEventHandler* progressUpdate) = 0;
        virtual HRESULT ExecuteJob(
            _Inout_ JobExecutionInfo* jobInfo) = 0;
        virtual HRESULT AnalyzeResults(
            _In_ AnalyzeResultsInfo* info) = 0;
        virtual HRESULT CancelAssessment(
            INT assessmentIndex) = 0;
        virtual HRESULT CancelJob() = 0;
        virtual HRESULT TerminateJob() = 0;
        virtual HRESULT RemovePendingRebootJob() = 0;
        virtual ~Engine(){}
    };

    // Job interface
    //
    struct Job : public IUnknown
    {
        virtual HRESULT GetName(
            _Outptr_opt_result_maybenull_z_ LPCWSTR* jobName) const = 0;
        virtual HRESULT GetToolTip(
            _Outptr_opt_result_maybenull_z_ LPCWSTR* toolTip) const = 0;
        virtual HRESULT GetAssessmentCount(
            _Out_ INT* count) const = 0;
        virtual HRESULT GetAssessment(
            _In_ INT assessmentIndex,
            _COM_Outptr_opt_result_maybenull_ const Assessment** assessment) const = 0;
        virtual HRESULT GetJobParameter(
            _In_z_ LPCWSTR parameterName,
            _Outptr_opt_result_maybenull_z_ LPCWSTR* parameterValue) const = 0;
        virtual HRESULT SetJobParameter(
            _In_z_ LPCWSTR parameterName,
            _In_z_ LPCWSTR parameterValue) = 0;
        virtual HRESULT CheckPrerequisites(
            _COM_Outptr_ PrerequisiteCollection** issues) = 0;
        virtual ~Job(){}
    };

    // Assessment interface
    //
    struct Assessment
    {
        virtual HRESULT GetName(
            _Outptr_opt_result_maybenull_z_ LPCWSTR* assessmentName) const = 0;
        virtual HRESULT GetProgrammaticName(
            _Outptr_opt_result_maybenull_z_ LPCWSTR* assessmentProgrammaticName) const = 0;
        virtual HRESULT GetToolTip(
            _Outptr_opt_result_maybenull_z_ LPCWSTR* toolTip) const = 0;
        virtual HRESULT GetId(
            _Out_ const GUID** guidAssessment) const = 0;
        virtual HRESULT GetFilePath(
            _Outptr_opt_result_maybenull_z_ LPCWSTR* assessmentPath) const = 0;
        virtual HRESULT GetSupportsAnalyze(
            _Out_ BOOL* analyze) const = 0;
        virtual HRESULT GetWorkloadAssessmentCount(
            _Out_ INT* count) const = 0;
        virtual HRESULT GetWorkloadAssessment(
            _In_ INT assessmentIndex,
            _COM_Outptr_opt_result_maybenull_ const Assessment** assessment) const = 0;
        virtual ~Assessment(){}
    };

    struct JobResults : public IUnknown
    {
        virtual HRESULT GetJobExecuted(
            _Outptr_ Job** job) = 0;
        virtual HRESULT AddAssessment(
            _In_z_ LPCWSTR path) = 0;
        virtual HRESULT AddAssessmentsFromJob(
            _In_z_ LPCWSTR path) = 0;
        virtual HRESULT GetAssessmentResults(
            _COM_Outptr_opt_result_maybenull_ AssessmentResultsCollection** result) const = 0;
        virtual HRESULT GetCanBeAnalyzed(
            _Out_ BOOL* analyze) const = 0;
        virtual HRESULT MarkAllToBeAnalyzed(
            _In_ BOOL analyze) = 0;
        virtual HRESULT GetToBeAnalyzedCount(
            _In_ INT* analyzeCount) const = 0;
        virtual ~JobResults(){}
    };

    struct AssessmentResultsCollection
    {
        virtual HRESULT GetCount(
            _Out_ INT* count) const = 0;
        virtual HRESULT GetItem(
            _In_ INT resultIndex,
            _COM_Outptr_opt_result_maybenull_ AssessmentResults** result) const = 0;
        virtual ~AssessmentResultsCollection(){}
    };

    struct AssessmentResults
    {
        virtual HRESULT GetAssessment(
            _Deref_out_ const Assessment** assessment) const = 0;
        virtual HRESULT GetCanBeAnalyzed(
            _Out_ CannotAnalyzeReason* reason) const = 0;
        virtual HRESULT GetToBeAnalyzed(
            _Out_ BOOL* analyze) const = 0;
        virtual HRESULT SetToBeAnalyzed(
            _In_ BOOL analyze) = 0;
        virtual ~AssessmentResults(){}
    };


} } }  // end namespace Microsoft::Assessments::Hosting


////////////////////////////////////////////////////////////////////////////////////////
// Factory function
////////////////////////////////////////////////////////////////////////////////////////

extern "C"
{
    HRESULT WINAPI AxeInitSolution(
        _In_opt_ Microsoft::Assessments::Hosting::SolutionParameters* pParams,
        _Outptr_opt_result_maybenull_ Microsoft::Assessments::Hosting::Solution** ppSolution);
    typedef HRESULT ( WINAPI * PFNAXE_INITSOLUTION)(
        _Inout_opt_ LPVOID pReserved,
        _Outptr_opt_result_maybenull_ Microsoft::Assessments::Hosting::Solution** ppSolution);
    #define AXE_INITSOLUTION "AxeInitSolution"
}

#endif  // NTDDI_VERSION >= NTDDI_WIN7

#endif  // AXEHOSTING_H
