//+---------------------------------------------------------------------------- // // Job Schedule Object Handler // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1996. // // File: job_cls.hxx // // Contents: job and triggers class objects header // // History: 23-May-95 EricB created // 06-Oct-95 EricB converted to produce lib // //----------------------------------------------------------------------------- #ifndef _JOB_CLS_HXX_ #define _JOB_CLS_HXX_ #include "dll.hxx" #include "common.hxx" #include "dynarray.hxx" #include "time.hxx" #include "runobj.hxx" #include #include class CJob; class CJobCF; class CSchedule; class CSchedWorker; #undef IsFlagSet #ifndef NOSTATIC #define Sign SAFunction20 #define VerifySignature SAFunction21 #define _SetSignature SAFunction22 #endif #define SIGNATURE_SIZE 64 // // Bit mask for the internal reserved portion of the bit flags. // #define JOB_INTERNAL_FLAG_MASK (0xffff8000) // // Values for CJob::m_rgFlags // // The upper word of the job flag property is reserved for internal use. // Lower word (public) values are defined in mstask.h (mstask.idl). // // Note that a job can have both JOB_I_FLAG_HAS_TRIGGERS and // JOB_I_FLAG_NO_VALID_TRIGGERS set. That means the triggers are either unset // or disabled. // #define JOB_I_FLAG_APPNAME_CHANGE (0x00010000) #define JOB_I_FLAG_SET_ACCOUNT_INFO (0x00020000) #define JOB_I_FLAG_NO_VALID_TRIGGERS (0x00040000) #define JOB_I_FLAG_LAST_LAUNCH_FAILED (0x00080000) #define JOB_I_FLAG_ERROR_IN_LAST_RUN (0x00100000) #define JOB_I_FLAG_NET_SCHEDULE (0x00200000) #define JOB_I_FLAG_NO_MORE_RUNS (0x00400000) // // The following flags are for determining job validity when the string // properties and triggers haven't been loaded. // #define JOB_I_FLAG_HAS_TRIGGERS (0x00800000) #define JOB_I_FLAG_HAS_APPNAME (0x01000000) #define JOB_I_FLAG_HAS_ACCOUNT (0x02000000) // // These flags are for job interface communication with the service. // #define JOB_I_FLAG_RUN_NOW (0x04000000) #define JOB_I_FLAG_ABORT_NOW (0x08000000) // // The following two flags are used to prevent unnecessary Wait List rebuilds. // CheckDir is called whenever there are changes made to job file objects. // If a change is caused by the service (when it updates the run status of a // job), we do not want the wait list to be rebuilt. If a change is caused by // a scheduler client, we do not want the wait list to be rebuilt *unless* the // change affects the job's run-ability. Those things that affect the run- // ability are run-time (triggers), adding or deleting an app name, or // toggling the disabled flag. We need both flags because we cannot control // the order that clients call the property and trigger modification methods. // See additonal comments about this in SaveP in persist.cxx. // #define JOB_I_FLAG_RUN_PROP_CHANGE (0x10000000) #define JOB_I_FLAG_NO_RUN_PROP_CHANGE (0x20000000) // // The top two bits are used as non-persistent dirty state flags. // #define JOB_DIRTY_FLAG_MASK (0xC0000000) #define JOB_I_FLAG_PROPERTIES_DIRTY (0x40000000) #define JOB_I_FLAG_TRIGGERS_DIRTY (0x80000000) #define JOB_I_FLAG_MISSED (0x00008000) // // Mask of non-persisted job flags. Masked off on save. // #define NON_PERSISTED_JOB_FLAGS (JOB_DIRTY_FLAG_MASK | \ JOB_I_FLAG_SET_ACCOUNT_INFO) // // Values for CTrigger::m_rgFlags // // The upper word of the trigger flag member is reserved for internal use. // Lower word (public) values are defined in mstask.h (mstask.idl). // #define JOB_TRIGGER_I_FLAG_NOT_SET (0x00010000) #define JOB_TRIGGER_I_FLAG_DURATION_AS_TIME (0x00020000) // // Values for CJob::SaveP flOptions parameter // #define SAVEP_VARIABLE_LENGTH_DATA (0x00000001) #define SAVEP_RUNNING_INSTANCE_COUNT (0x00000002) #define SAVEP_PRESERVE_NET_SCHEDULE (0x00000004) // // This macro can be used within methods of CJob // #define DELETE_CJOB_FIELD(m_pField) \ if (!m_MainBlock.Contains(m_pField)) \ { \ delete [] (m_pField); \ } \ m_pField = NULL; // else it will be deleted by m_MainBlock.Set() or ~m_MainBlock() //+---------------------------------------------------------------------------- // // Class: CTrigger // // Purpose: Trigger object - represents a job run time repetition period // //----------------------------------------------------------------------------- class CTrigger : public ITaskTrigger { friend CJob; friend CSchedule; public: CTrigger(WORD iTrigger, CJob * pJob); ~CTrigger(void); // IUnknown methods STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject); STDMETHOD_(ULONG, AddRef)(void); STDMETHOD_(ULONG, Release)(void); // ITaskTrigger methods STDMETHOD(SetTrigger)(const PTASK_TRIGGER pTrigger); STDMETHOD(GetTrigger)(PTASK_TRIGGER pTrigger); STDMETHOD(GetTriggerString)(LPWSTR * ppwszTrigger); private: CJob * m_pJob; // Parent job object. WORD m_iTrigger; // TASK_TRIGGER index. ULONG m_cReferences; }; //+---------------------------------------------------------------------------- // // Class: CInputBuffer // // Synopsis: Used by CJob::LoadP to parse a buffer containing the contents // of a task file. Using this class is less bug-prone than // using two pointer variables. // BOOL methods return FALSE on buffer overrun. // //----------------------------------------------------------------------------- class CInputBuffer { private: const BYTE * _pCurrent; // Current position in buffer const BYTE * const _pEnd; // First invalid position in buffer public: CInputBuffer(const BYTE * pCurrent, const BYTE * pEnd) : _pCurrent(pCurrent), _pEnd(pEnd) { } BYTE * CurrentPosition() { return (BYTE *) _pCurrent; } BOOL Advance(DWORD cb) { _pCurrent += cb; return (_pCurrent <= _pEnd); } BOOL Read(void * pDest, DWORD cb) { if (_pCurrent + cb <= _pEnd) { CopyMemory(pDest, _pCurrent, cb); _pCurrent += cb; return TRUE; } else { return FALSE; } } }; //+---------------------------------------------------------------------------- // // Class: CHeapBlock // // Synopsis: Variable-length properties of CJob that are read by LoadP // are held in a single heap block, the original block which // the task file was read from disk into, as long as they are // not dirtied. If any one is dirtied a separate heap block // is allocated for it. This class helps manage the original // heap block. // //----------------------------------------------------------------------------- class CHeapBlock { private: BYTE * _pStart; // Start of the heap block const BYTE * _pEnd; // First byte past the end of the heap block public: CHeapBlock() : _pStart(NULL), _pEnd(NULL) { } ~CHeapBlock() { delete [] _pStart; } void Set(BYTE * pStart, DWORD dwSize) { delete [] _pStart; _pStart = pStart; _pEnd = _pStart + dwSize; } BOOL Contains(void * p) { return (_pStart <= (BYTE *)p && (BYTE *)p < _pEnd); } }; typedef struct _FIXDLENDATA { WORD wVersion; WORD wFileObjVer; UUID uuidJob; WORD wAppNameLenOffset; WORD wTriggerOffset; WORD wErrorRetryCount; WORD wErrorRetryInterval; WORD wIdleDeadline; WORD wIdleWait; DWORD dwPriority; DWORD dwMaxRunTime; HRESULT ExitCode; HRESULT hrStatus; DWORD rgFlags; SYSTEMTIME stMostRecentRunTime; } FIXDLEN_DATA, * PFIXDLEN_DATA; typedef struct _TASKRESERVED1 { HRESULT hrStartError; DWORD rgTaskFlags; } TASKRESERVED1, * PTASKRESERVED1; typedef struct _JOB_ACCOUNT_INFO { WCHAR * pwszAccount; WCHAR * pwszPassword; } JOB_ACCOUNT_INFO, * PJOB_ACCOUNT_INFO; //+---------------------------------------------------------------------------- // // Class: CJob // // Purpose: Job object // //----------------------------------------------------------------------------- class CJob : public ITask, public IPersistFile, public IProvideTaskPage { friend CTrigger; friend CJobCF; friend CSchedule; friend CSchedWorker; public: CJob(); ~CJob(); // IUnknown methods STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject); STDMETHOD_(ULONG, AddRef)(void); STDMETHOD_(ULONG, Release)(void); // ITask methods STDMETHOD(Run)(void); STDMETHOD(Terminate)(void); STDMETHOD(EditWorkItem)(HWND hParent, DWORD dwReserved); STDMETHOD(CreateTrigger)(WORD * piNewTrigger, ITaskTrigger ** ppTrigger); STDMETHOD(DeleteTrigger)(WORD iTrigger); STDMETHOD(GetTriggerCount)(WORD * pwCount); STDMETHOD(GetTrigger)(WORD iTrigger, ITaskTrigger ** ppTrigger); STDMETHOD(GetTriggerString)(WORD iTrigger, LPWSTR * ppwszTrigger); STDMETHOD(GetRunTimes)(const LPSYSTEMTIME pstBegin, const LPSYSTEMTIME pstEnd, WORD * pwCount, LPSYSTEMTIME * rgstJobTimes); // ITask properties STDMETHOD(SetApplicationName)(LPCWSTR pwszApplicationName); STDMETHOD(GetApplicationName)(LPWSTR * ppwszApplicationName); STDMETHOD(SetParameters)(LPCWSTR pwszParameters); STDMETHOD(GetParameters)(LPWSTR * ppwszParameters); STDMETHOD(SetWorkingDirectory)(LPCWSTR pwszWorkingDirectory); STDMETHOD(GetWorkingDirectory)(LPWSTR * ppwszWorkingDirectory); STDMETHOD(SetAccountInformation)(LPCWSTR pwszAccountName, LPCWSTR pwszPassword); STDMETHOD(GetAccountInformation)(LPWSTR * ppwszAccountName); STDMETHOD(SetComment)(LPCWSTR pwszComment); STDMETHOD(GetComment)(LPWSTR * ppwszComment); STDMETHOD(SetPriority)(DWORD dwPriority); STDMETHOD(GetPriority)(DWORD * pdwPriority); STDMETHOD(SetMaxRunTime)(DWORD dwMaxRunTime); STDMETHOD(GetMaxRunTime)(DWORD * pdwMaxRunTime); STDMETHOD(SetIdleWait)(WORD wIdleMinutes, WORD wDeadlineMinutes); STDMETHOD(GetIdleWait)(WORD * pwIdleMinutes, WORD * pwDeadlineMinutes); STDMETHOD(SetErrorRetryCount)(WORD wRetryCount); STDMETHOD(GetErrorRetryCount)(WORD * pwRetryCount); STDMETHOD(SetErrorRetryInterval)(WORD wRetryInterval); STDMETHOD(GetErrorRetryInterval)(WORD * pwRetryInterval); STDMETHOD(SetFlags)(DWORD dwJobFlags); STDMETHOD(GetFlags)(DWORD * pdwJobFlags); STDMETHOD(SetTaskFlags)(DWORD dwJobFlags); STDMETHOD(GetTaskFlags)(DWORD * pdwJobFlags); STDMETHOD(SetWorkItemData)(WORD cbData, BYTE rgbData[]); STDMETHOD(GetWorkItemData)(PWORD pcbData, PBYTE * prgbData); STDMETHOD(GetMostRecentRunTime)(SYSTEMTIME * pstLastRun); STDMETHOD(GetNextRunTime)(SYSTEMTIME * pstNextRun); STDMETHOD(GetExitCode)(DWORD * pExitCode); STDMETHOD(GetStatus)(HRESULT * pStatus); STDMETHOD(SetCreator)(LPCWSTR pwszCreator); STDMETHOD(GetCreator)(LPWSTR * ppwszCreator); // IPersist method STDMETHOD(GetClassID)(CLSID * pClsID); // IPersistFile methods STDMETHOD(IsDirty)(void); STDMETHOD(Load)(LPCOLESTR pwszFileName, DWORD dwMode); STDMETHOD(Save)(LPCOLESTR pwszFileName, BOOL fRemember); STDMETHOD(SaveCompleted)(LPCOLESTR pwszFileName); STDMETHOD(GetCurFile)(LPOLESTR * ppwszFileName); // IProvideTaskPage method STDMETHOD(GetPage)(TASKPAGE tpType, BOOL fPersistChanges, HPROPSHEETPAGE * phPage); // CJob methods static CJob * Create(void) { return (new CJob); } HRESULT LoadP(LPCTSTR ptszFileName, DWORD dwMode, BOOL fRemember, BOOL fAllData); HRESULT SaveP(LPCTSTR ptszFileName, BOOL fRemember, ULONG flOptions = 0); HRESULT LoadTriggers(void); HRESULT UpdateJobState(BOOL fRunning); HRESULT PostRunUpdate(long ExitCode, BOOL fFinishedOK); LPCWSTR GetCommand(void) const { return(m_pwszApplicationName); } LPTSTR GetFileName(void) const { return(m_ptszFileName); } HRESULT SetTrigger(WORD iTrigger, PTASK_TRIGGER pTrigger); HRESULT GetTrigger(WORD iTrigger, PTASK_TRIGGER pTrigger); void GetAllFlags(DWORD * pFlags) {*pFlags = m_rgFlags;} HRESULT GetRunTimesP(const SYSTEMTIME * pstBegin, const SYSTEMTIME * pstEnd, WORD * pCount, WORD cLimit, CTimeRunList * pRunList, LPTSTR ptszShortJobName); void SetStartError(HRESULT hrStartError) { m_hrStartError = hrStartError; } #if !defined(_CHICAGO_) HRESULT Sign(void); BOOL VerifySignature(void) const; HRESULT GetAtInfo(PAT_INFO pAt, LPWSTR pwszCommand, DWORD * pcchCommand); #endif BOOL IsFlagSet(DWORD dwBitFlag) {return m_rgFlags & dwBitFlag;} protected: void SetTriggersDirty(void); void SetFlag(DWORD dwBitFlag) {m_rgFlags |= dwBitFlag;} void ClearFlag(DWORD dwBitFlag) {m_rgFlags &= ~dwBitFlag;} DWORD GetUserFlags(void) {return m_rgFlags & ~JOB_INTERNAL_FLAG_MASK;} BOOL IsStatus(HRESULT hr) {return m_hrStatus == hr;} void SetStatus(HRESULT hr) {m_hrStatus = hr;} HRESULT IfStartupJobAddToList(LPTSTR ptszJobName, CRunList * pRunList, CIdleRunList * pIdleWaitList); HRESULT IfLogonJobAddToList(LPTSTR ptszJobName, CRunList * pRunList, CIdleRunList * pIdleWaitList); HRESULT IfIdleJobAddToList(LPTSTR ptszJobName, CIdleRunList * pRunList); HRESULT Delete(void); private: HRESULT IfEventJobAddToList(TASK_TRIGGER_TYPE Type, LPCTSTR ptszJobName, CRunList * pRunList, CIdleRunList * pIdleWaitList); void FreeProperties(void); TASK_TRIGGER * _GetTrigger(WORD iTrigger); HRESULT _LoadTriggers(HANDLE hFile); HRESULT _LoadTriggersFromBuffer(CInputBuffer * pBuf); HRESULT _SaveTriggers(HANDLE hFile); HRESULT _SetSignature(const BYTE * pbSignature); // Properties: CDynamicArray m_Triggers; WORD m_wVersion; WORD m_wFileObjVer; UUID m_uuidJob; WORD m_wTriggerOffset; WORD m_wErrorRetryCount; WORD m_wErrorRetryInterval; WORD m_cRunningInstances; WORD m_wIdleWait; WORD m_wIdleDeadline; DWORD m_dwPriority; DWORD m_dwMaxRunTime; DWORD m_ExitCode; HRESULT m_hrStatus; DWORD m_rgFlags; DWORD m_rgTaskFlags; SYSTEMTIME m_stMostRecentRunTime; LPWSTR m_pwszApplicationName; // [*] LPWSTR m_pwszParameters; // [*] LPWSTR m_pwszWorkingDirectory; // [*] LPWSTR m_pwszCreator; // [*] LPWSTR m_pwszComment; // [*] LPTSTR m_ptszFileName; BOOL m_fFileCreated; PBYTE m_pbTaskData; // [*] WORD m_cbTaskData; WORD m_cReserved; PBYTE m_pbReserved; // [*] HRESULT m_hrStartError; #if !defined(_CHICAGO_) PJOB_ACCOUNT_INFO m_pAccountInfo; // Allocated exclusively in // the SetAccountInformation member. PBYTE m_pbSignature; // [*] #endif // !defined(_CHICAGO_) CHeapBlock m_MainBlock; // Initially holds properties marked [*] // State data: ITypeInfo * m_pIJobTypeInfo; unsigned long m_cReferences; CDllRef m_DllRef; // Static members static LPWSTR CJob::* const s_StringField[]; }; //+---------------------------------------------------------------------------- // // Class: CJobCF // // Purpose: job object class factory // //----------------------------------------------------------------------------- class CJobCF : public IClassFactory { public: CJobCF(); // IUnknown methods STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject); STDMETHOD_(ULONG, AddRef)(); STDMETHOD_(ULONG, Release)(); // IClassFactory methods STDMETHOD(CreateInstance)(IUnknown *pUnkOuter, REFIID riid, void **ppvObject); STDMETHOD(LockServer)(BOOL fLock); static IClassFactory * Create(void); protected: ~CJobCF(); unsigned long m_uRefs; CDllRef m_DllRef; }; #endif // _JOB_CLS_HXX_