/************************************************************************ Copyright (c) 2000 - 2000 Microsoft Corporation Module Name : cmanager.h Abstract : Header file for the CJobManager interface. Author : Revision History : ***********************************************************************/ #pragma once #include "qmgrlib.h" #include #include "clist.h" #include "logontable.h" #include "drizcpat.h" #include "bitstest.h" #include using namespace std; class CJob; class CJobManagerFactory; class CJobManager; class CJobManagerExternal; class CJobList : public IntrusiveList { public: BOOL Add( CJob * job ); CJob * Find( REFGUID id ); BOOL Remove( CJob * job ); ~CJobList(); void Serialize( HANDLE hFile ); void Unserialize( HANDLE hFile ); void Clear(); typedef IntrusiveList::iterator iterator; }; class CJobManagerExternal : public IBackgroundCopyManager, public IClassFactory, public IBitsTest1 { public: friend CJobManager; // IUnknown methods // STDMETHOD(QueryInterface)(REFIID iid, void** ppvObject); ULONG __stdcall AddRef(void); ULONG __stdcall Release(void); // IBackgroundCopyManager methods HRESULT STDMETHODCALLTYPE CreateJobInternal( /* [in] */ LPCWSTR DisplayName, /* [in] */ BG_JOB_TYPE Type, /* [out] */ GUID *pJobId, /* [out] */ IBackgroundCopyJob **ppJob); HRESULT STDMETHODCALLTYPE CreateJob( /* [in] */ LPCWSTR DisplayName, /* [in] */ BG_JOB_TYPE Type, /* [out] */ GUID *pJobId, /* [out] */ IBackgroundCopyJob **ppJob) { EXTERNAL_FUNC_WRAP( CreateJobInternal( DisplayName, Type, pJobId, ppJob ) ) } HRESULT STDMETHODCALLTYPE GetJobInternal( /* [in] */ REFGUID jobID, /* [out] */ IBackgroundCopyJob **ppJob); HRESULT STDMETHODCALLTYPE GetJob( /* [in] */ REFGUID jobID, /* [out] */ IBackgroundCopyJob **ppJob) { EXTERNAL_FUNC_WRAP( GetJobInternal( jobID, ppJob ) ) } HRESULT STDMETHODCALLTYPE EnumJobsInternal( /* [in] */ DWORD dwFlags, /* [out] */ IEnumBackgroundCopyJobs **ppEnum); HRESULT STDMETHODCALLTYPE EnumJobs( /* [in] */ DWORD dwFlags, /* [out] */ IEnumBackgroundCopyJobs **ppEnum) { EXTERNAL_FUNC_WRAP( EnumJobsInternal( dwFlags, ppEnum ) ) } HRESULT STDMETHODCALLTYPE GetErrorDescriptionInternal( /* [in] */ HRESULT hResult, /* [in] */ DWORD LanguageId, /* [out] */ LPWSTR *pErrorDescription ); HRESULT STDMETHODCALLTYPE GetErrorDescription( /* [in] */ HRESULT hResult, /* [in] */ DWORD LanguageId, /* [out] */ LPWSTR *pErrorDescription ) { EXTERNAL_FUNC_WRAP( GetErrorDescriptionInternal( hResult, LanguageId, pErrorDescription ) ) } // IClassFactory methods HRESULT __stdcall CreateInstance(IUnknown* pUnkOuter, REFIID iid, void** ppvObject); HRESULT __stdcall LockServer(BOOL fLock); // IBitsTest1 methods virtual HRESULT STDMETHODCALLTYPE GetBitsDllPath( /* [out] */ LPWSTR *pVal); protected: long m_ServiceInstance; CJobManager *m_pJobManager; long m_refs; CJobManagerExternal(); void SetInterfaceClass( CJobManager *pVal ) { m_pJobManager = pVal; } void NotifyInternalDelete() { // Release the internal refcount Release(); } }; class CDeviceNotificationController { public: virtual ~CDeviceNotificationController(); // General message cracker DWORD OnDeviceEvent( DWORD dwEventType, LPVOID lpEventData ); // Event methods virtual void OnDeviceLock( const WCHAR *CanonicalVolume ) = 0; virtual void OnDeviceUnlock( const WCHAR *CanonicalVolume ) = 0; virtual void OnDismount( const WCHAR *CanonicalVolume ) = 0; HRESULT RegisterNotification( const WCHAR *CanonicalVolume ); HRESULT IsVolumeLocked( const WCHAR *CanonicalVolume ); private: class CDriveNotify { public: HDEVNOTIFY m_hDeviceNotify; StringHandle m_CanonicalName; LONG m_LockCount; LONG m_RemoveCount; CDriveNotify( HDEVNOTIFY hDeviceNotify, StringHandle CanonicalName ) : m_hDeviceNotify( hDeviceNotify ), m_CanonicalName( CanonicalName ), m_RemoveCount( 0 ), m_LockCount( 0 ) { } }; typedef map CHandleToNotify; typedef map CCanonicalVolumeToNotify; CHandleToNotify m_HandleToNotify; CCanonicalVolumeToNotify m_CanonicalVolumeToNotify; void DeleteNotify( CDriveNotify *pNotify ); }; class CBitsVssWriter : public CVssWriter /* CVssWriter is a backup-related class implemented by the system. In October 2002 it was available only on Windows XP and higher. The default implementation does nothing; BITS ovverrides OnIdentify() to exclude its job temporary and metadata files from the list to be backed up. */ { public: virtual bool STDMETHODCALLTYPE OnIdentify(IVssCreateWriterMetadata *pMetadata); // // Additional vitrual functions required by CVssWriter but not used by our implementation. // // callback if current sequence is aborted virtual bool STDMETHODCALLTYPE OnAbort() { return true; } // callback for prepare snapsot event virtual bool STDMETHODCALLTYPE OnPrepareSnapshot() { return true; } // callback for freeze event virtual bool STDMETHODCALLTYPE OnFreeze() { return true; } // callback for thaw event virtual bool STDMETHODCALLTYPE OnThaw() { return true; } }; class CJobManager : public TaskSchedulerWorkItem, private CDeviceNotificationController, public CQmgrStateFiles { public: friend CJobManagerExternal; friend COldQmgrInterface; HRESULT CreateJob( LPCWSTR DisplayName, BG_JOB_TYPE Type, GUID Id, SidHandle sid, CJob ** ppJob, bool OldStyleJob = false ); // Returns NULL if job not found HRESULT GetJob( REFGUID jobID, CJob ** ppJob ); // // TaskSchedulerWorkItem methods // void OnDispatch() { TransferCurrentJob(); } SidHandle GetSid() { return g_GlobalInfo->m_LocalSystemSid; } // CDeviceNotificationController methods DWORD OnDeviceEvent( DWORD dwEventType, LPVOID lpEventData ) { LockWriter(); DWORD dwResult = CDeviceNotificationController::OnDeviceEvent( dwEventType, lpEventData ); UnlockWriter(); return dwResult; } // // additional functions // CJobManager(); virtual ~CJobManager(); // // Notification that a user has logged on. // void SYNCHRONIZED_WRITE UserLoggedOn( SidHandle sid ); // // Notification that a user has logged off. // void SYNCHRONIZED_WRITE UserLoggedOff( SidHandle sid ); // // Notification that there was a change in the number of active network adapters. // void OnNetworkChange(); // // Called by m_BackupWriter->OnIdentify. // bool OnIdentify( IN IVssCreateWriterMetadata *pMetadata ); // // Adjust the job's online/offline state after its owner changes. // void ResetOnlineStatus( CJob *pJob, SidHandle sid ); void ScheduleDelayedTask( TaskSchedulerWorkItem * task, ULONG SecondsOfDelay ) { FILETIME TimeToRun = GetTimeAfterDelta( (UINT64) NanoSec100PerSec * SecondsOfDelay ); m_TaskScheduler.InsertWorkItem( task, &TimeToRun ); } void TaskThread(); HRESULT SuspendJob ( CJob * job ); HRESULT ResumeJob ( CJob * job ); HRESULT CancelJob ( CJob * job ); HRESULT CompleteJob( CJob * job ); HRESULT Serialize(); HRESULT Unserialize(); bool LockReader() { return m_TaskScheduler.LockReader(); } void UnlockReader() { m_TaskScheduler.UnlockReader(); } bool LockWriter() { return m_TaskScheduler.LockWriter(); } void UnlockWriter() { m_TaskScheduler.UnlockWriter(); } // // recalculates which job should be downloading and kicks the download thread if necessary. // void ScheduleAnotherGroup( bool fInsertNetworkDelay = false ); void MoveJobOffline( CJob * job ); void AppendOnline( CJob * job ); void Shutdown(); HRESULT CloneUserToken( SidHandle psid, DWORD session, HANDLE * pToken ); bool IsUserLoggedOn( SidHandle psid ); HRESULT RegisterClassObjects(); void RevokeClassObjects(); HRESULT CreateBackupWriter(); void DeleteBackupWriter(); //-------------------------------------------------------------------- CJobManagerExternal* GetExternalInterface() { return m_ExternalInterface; } COldQmgrInterface* GetOldExternalInterface() { return m_OldQmgrInterface; } void NotifyInternalDelete() { GetExternalInterface()->NotifyInternalDelete(); } HRESULT GetErrorDescription( HRESULT hResult, DWORD LanguageId, LPWSTR *pErrorDescription ); Downloader * m_pPD; TaskScheduler m_TaskScheduler; void OnDiskChange( const WCHAR *CanonicalVolume, DWORD VolumeSerialNumber ); HRESULT IsVolumeLocked( const WCHAR *CanonicalPath ) { return CDeviceNotificationController::IsVolumeLocked( CanonicalPath ); } void RetaskJob( CJob *pJob ); void InterruptDownload(); void MoveJobToInactiveState( CJob * job ); bool RemoveJob( CJob * job ) { if (m_OnlineJobs.Remove( job )) { return true; } if (m_OfflineJobs.Remove( job )) { return true; } return false; } HRESULT CheckClientAccess(); private: CJob * m_CurrentJob; HMODULE m_hWininet; HANDLE m_hQuantumTimer; // cookies from CoRegisterClassObject. // used later to unregister. // DWORD m_ComId_1_5; DWORD m_ComId_1_0; DWORD m_ComId_0_5; CJobList m_OnlineJobs; CJobList m_OfflineJobs; CJobManagerExternal * m_ExternalInterface; COldQmgrInterface * m_OldQmgrInterface; public: CLoggedOnUsers m_Users; CIpAddressMonitor m_NetworkMonitor; private: CBitsVssWriter * m_BackupWriter; HMODULE m_hVssapi_dll; //-------------------------------------------------------------------- HRESULT GetCurrentGroupAndToken( HANDLE * pToken ); void TransferCurrentJob(); void ChooseCurrentJob(); void Cleanup(); // Returns the runing or queued jobs that have // a priority >= current priority. size_t MoveActiveJobToListEnd( CJob *pJob ); void SetQuantumTimeout(); public: bool CheckForQuantumTimeout(); void UpdateRemoteSizes( CUnknownFileSizeList *pUnknownFileSizeList, HANDLE hToken, QMErrInfo *pErrorInfo, const PROXY_SETTINGS * ProxySettings, const CCredentialsContainer * Credentials ); private: // Event methods void OnDeviceLock( const WCHAR *CanonicalVolume ); void OnDeviceUnlock( const WCHAR *CanonicalVolume ); void OnDismount( const WCHAR *CanonicalVolume ); // methods for dealing with network topology changes // static void CALLBACK NetworkChangeCallback( PVOID arg ); void MarkJobsWithNetDisconnected(); void ReactivateTransientErrorJobs(); }; class CLockedJobManagerReadPointer { CJobManager * const m_Pointer; public: CLockedJobManagerReadPointer( CJobManager * Pointer) : m_Pointer(Pointer) { m_Pointer->LockReader(); } ~CLockedJobManagerReadPointer() { m_Pointer->UnlockReader(); } CJobManager * operator->() const { return m_Pointer; } HRESULT ValidateAccess() { return m_Pointer->CheckClientAccess(); } }; class CLockedJobManagerWritePointer { CJobManager * const m_Pointer; public: CLockedJobManagerWritePointer( CJobManager * Pointer) : m_Pointer(Pointer) { m_Pointer->LockWriter(); } ~CLockedJobManagerWritePointer() { m_Pointer->UnlockWriter(); } CJobManager * operator->() const { return m_Pointer; } HRESULT ValidateAccess() { return m_Pointer->CheckClientAccess(); } }; extern CJobManagerFactory * g_ManagerFactory; extern CJobManager * g_Manager; // SENS logon notification void ActivateSensLogonNotification(); void DeactiveateSensLogonNotification(); extern MANAGER_STATE g_ServiceState; extern long g_ServiceInstance; /** * Checks to see if a given job is being downloaded. * If so, the constructor interrupts the download, and * the destructor calls CJobManager::ScheduleAnotherJob(). * * This is useful for methods that change job properties, * when those changes affect the download itself. */ class CRescheduleDownload { bool bRunning; public: CRescheduleDownload( CJob * job ) { bRunning = job->IsRunning(); if (bRunning) { g_Manager->InterruptDownload(); } } ~CRescheduleDownload() { if (bRunning) { g_Manager->ScheduleAnotherGroup(); } } };