/** @file * * VirtualBox COM class implementation */ /* * Copyright (C) 2006 InnoTek Systemberatung GmbH * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License as published by the Free Software Foundation, * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE * distribution. VirtualBox OSE is distributed in the hope that it will * be useful, but WITHOUT ANY WARRANTY of any kind. * * If you received this file as part of a commercial VirtualBox * distribution, then only the terms of your commercial VirtualBox * license agreement apply instead of the previous paragraph. */ #ifndef ____H_PROGRESSIMPL #define ____H_PROGRESSIMPL #include "VirtualBoxBase.h" #include "Collection.h" #include #include class VirtualBox; //////////////////////////////////////////////////////////////////////////////// class ATL_NO_VTABLE ProgressBase : public VirtualBoxSupportErrorInfoImpl , public VirtualBoxSupportTranslation , public VirtualBoxBase, public IProgress { protected: BEGIN_COM_MAP(ProgressBase) COM_INTERFACE_ENTRY(ISupportErrorInfo) COM_INTERFACE_ENTRY(IProgress) END_COM_MAP() HRESULT FinalConstruct(); // public initializer/uninitializer for internal purposes only HRESULT protectedInit ( #if !defined (VBOX_COM_INPROC) VirtualBox *aParent, #endif IUnknown *aInitiator, const BSTR aDescription, GUIDPARAMOUT aId = NULL); HRESULT protectedInit(); void protectedUninit (AutoLock &alock); public: // IProgress properties STDMETHOD(COMGETTER(Id)) (GUIDPARAMOUT aId); STDMETHOD(COMGETTER(Description)) (BSTR *aDescription); STDMETHOD(COMGETTER(Initiator)) (IUnknown **aInitiator); // IProgress properties STDMETHOD(COMGETTER(Cancelable)) (BOOL *aCancelable); STDMETHOD(COMGETTER(Percent)) (LONG *aPercent); STDMETHOD(COMGETTER(Completed)) (BOOL *aCompleted); STDMETHOD(COMGETTER(Canceled)) (BOOL *aCanceled); STDMETHOD(COMGETTER(ResultCode)) (HRESULT *aResultCode); STDMETHOD(COMGETTER(ErrorInfo)) (IVirtualBoxErrorInfo **aErrorInfo); STDMETHOD(COMGETTER(OperationCount)) (ULONG *aOperationCount); STDMETHOD(COMGETTER(Operation)) (ULONG *aCount); STDMETHOD(COMGETTER(OperationDescription)) (BSTR *aOperationDescription); STDMETHOD(COMGETTER(OperationPercent)) (LONG *aOperationPercent); // public methods only for internal purposes Guid id() { AutoLock alock (this); return mId; } BOOL completed() { AutoLock alock (this); return mCompleted; } HRESULT resultCode() { AutoLock alock (this); return mResultCode; } // for VirtualBoxSupportErrorInfoImpl static const wchar_t *getComponentName() { return L"Progress"; } protected: #if !defined (VBOX_COM_INPROC) /** weak parent */ ComObjPtr mParent; #endif ComPtr mInitiator; Guid mId; Bstr mDescription; // the fields below are to be initalized by subclasses BOOL mCompleted; BOOL mCancelable; BOOL mCanceled; HRESULT mResultCode; ComPtr mErrorInfo; ULONG mOperationCount; ULONG mOperation; Bstr mOperationDescription; LONG mOperationPercent; }; //////////////////////////////////////////////////////////////////////////////// class ATL_NO_VTABLE Progress : public VirtualBoxSupportTranslation , public ProgressBase { public: VIRTUALBOXSUPPORTTRANSLATION_OVERRIDE(Progress) DECLARE_NOT_AGGREGATABLE(Progress) DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(Progress) COM_INTERFACE_ENTRY(ISupportErrorInfo) COM_INTERFACE_ENTRY(IProgress) END_COM_MAP() NS_DECL_ISUPPORTS HRESULT FinalConstruct(); void FinalRelease(); // public initializer/uninitializer for internal purposes only HRESULT init ( #if !defined (VBOX_COM_INPROC) VirtualBox *aParent, #endif IUnknown *aInitiator, const BSTR aDescription, BOOL aCancelable, GUIDPARAMOUT aId = NULL) { return init ( #if !defined (VBOX_COM_INPROC) aParent, #endif aInitiator, aDescription, aCancelable, 1, aDescription, aId); } HRESULT init ( #if !defined (VBOX_COM_INPROC) VirtualBox *aParent, #endif IUnknown *aInitiator, const BSTR aDescription, BOOL aCancelable, ULONG aOperationCount, const BSTR aOperationDescription, GUIDPARAMOUT aId = NULL); HRESULT init (BOOL aCancelable, ULONG aOperationCount, const BSTR aOperationDescription); void uninit(); // IProgress methods STDMETHOD(WaitForCompletion) (LONG aTimeout); STDMETHOD(WaitForOperationCompletion) (ULONG aOperation, LONG aTimeout); STDMETHOD(Cancel)(); // public methods only for internal purposes HRESULT notifyProgress (LONG aPercent); HRESULT advanceOperation (const BSTR aOperationDescription); HRESULT notifyComplete (HRESULT aResultCode); HRESULT notifyComplete (HRESULT aResultCode, const GUID &aIID, const Bstr &aComponent, const char *aText, ...); HRESULT notifyCompleteBstr (HRESULT aResultCode, const GUID &aIID, const Bstr &aComponent, const Bstr &aText); private: RTSEMEVENTMULTI mCompletedSem; ULONG mWaitersCount; }; //////////////////////////////////////////////////////////////////////////////// /** * The CombinedProgress class allows to combine several progress objects * to a single progress component. This single progress component will treat * all operations of individual progress objects as a single sequence of * operations, that follow each other in the same order as progress objects are * passed to the #init() method. * * Individual progress objects are sequentially combined so that this progress * object: * * - is cancelable only if all progresses are cancelable. * - is canceled once a progress that follows next to successfully completed * ones reports it was canceled. * - is completed successfully only after all progresses are completed * successfully. * - is completed unsuccessfully once a progress that follows next to * successfully completed ones reports it was completed unsuccessfully; * the result code and error info of the unsuccessful progress * will be reported as the result code and error info of this progress. * - returns N as the operation number, where N equals to the number of * operations in all successfully completed progresses starting from the * first one plus the operation number of the next (not yet complete) * progress; the operation description of the latter one is reported as * the operation description of this progress object. * - returns P as the percent value, where P equals to the sum of percents * of all successfully completed progresses starting from the * first one plus the percent value of the next (not yet complete) * progress, normalized to 100%. * * @note * It's the respoisibility of the combined progress object creator * to complete individual progresses in the right order: if, let's say, * the last progress is completed before all previous ones, * #WaitForCompletion(-1) will most likely give 100% CPU load because it * will be in a loop calling a method that returns immediately. */ class ATL_NO_VTABLE CombinedProgress : public VirtualBoxSupportTranslation , public ProgressBase { public: VIRTUALBOXSUPPORTTRANSLATION_OVERRIDE(CombinedProgress) DECLARE_NOT_AGGREGATABLE(CombinedProgress) DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(CombinedProgress) COM_INTERFACE_ENTRY(ISupportErrorInfo) COM_INTERFACE_ENTRY(IProgress) END_COM_MAP() NS_DECL_ISUPPORTS HRESULT FinalConstruct(); void FinalRelease(); // public initializer/uninitializer for internal purposes only HRESULT init ( #if !defined (VBOX_COM_INPROC) VirtualBox *aParent, #endif IUnknown *aInitiator, const BSTR aDescription, IProgress *aProgress1, IProgress *aProgress2, GUIDPARAMOUT aId = NULL) { AutoLock lock (this); ComAssertRet (!isReady(), E_UNEXPECTED); mProgresses.resize (2); mProgresses [0] = aProgress1; mProgresses [1] = aProgress2; return protectedInit ( #if !defined (VBOX_COM_INPROC) aParent, #endif aInitiator, aDescription, aId); } template HRESULT init ( #if !defined (VBOX_COM_INPROC) VirtualBox *aParent, #endif IUnknown *aInitiator, const BSTR aDescription, InputIterator aFirstProgress, InputIterator aLastProgress, GUIDPARAMOUT aId = NULL) { AutoLock lock (this); ComAssertRet (!isReady(), E_UNEXPECTED); mProgresses = ProgressVector (aFirstProgress, aLastProgress); return protectedInit ( #if !defined (VBOX_COM_INPROC) aParent, #endif aInitiator, aDescription, aId); } protected: HRESULT protectedInit ( #if !defined (VBOX_COM_INPROC) VirtualBox *aParent, #endif IUnknown *aInitiator, const BSTR aDescription, GUIDPARAMOUT aId); public: void uninit(); // IProgress properties STDMETHOD(COMGETTER(Percent)) (LONG *aPercent); STDMETHOD(COMGETTER(Completed)) (BOOL *aCompleted); STDMETHOD(COMGETTER(Canceled)) (BOOL *aCanceled); STDMETHOD(COMGETTER(ResultCode)) (HRESULT *aResultCode); STDMETHOD(COMGETTER(ErrorInfo)) (IVirtualBoxErrorInfo **aErrorInfo); STDMETHOD(COMGETTER(Operation)) (ULONG *aCount); STDMETHOD(COMGETTER(OperationDescription)) (BSTR *aOperationDescription); STDMETHOD(COMGETTER(OperationPercent)) (LONG *aOperationPercent); // IProgress methods STDMETHOD(WaitForCompletion) (LONG aTimeout); STDMETHOD(WaitForOperationCompletion) (ULONG aOperation, LONG aTimeout); STDMETHOD(Cancel)(); // public methods only for internal purposes private: HRESULT checkProgress(); typedef std::vector > ProgressVector; ProgressVector mProgresses; size_t mProgress; ULONG mCompletedOperations; }; COM_DECL_READONLY_ENUM_AND_COLLECTION_AS (Progress, IProgress) #endif // ____H_PROGRESSIMPL