Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

524 lines
18 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Job Schedule Object Handler
  4. //
  5. // Microsoft Windows
  6. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  7. //
  8. // File: job_cls.hxx
  9. //
  10. // Contents: job and triggers class objects header
  11. //
  12. // History: 23-May-95 EricB created
  13. // 06-Oct-95 EricB converted to produce lib
  14. //
  15. //-----------------------------------------------------------------------------
  16. #ifndef _JOB_CLS_HXX_
  17. #define _JOB_CLS_HXX_
  18. #include "dll.hxx"
  19. #include "common.hxx"
  20. #include "dynarray.hxx"
  21. #include "time.hxx"
  22. #include "runobj.hxx"
  23. #include <mstask.h>
  24. #include <msterr.h>
  25. class CJob;
  26. class CJobCF;
  27. class CSchedule;
  28. class CSchedWorker;
  29. #undef IsFlagSet
  30. #ifndef NOSTATIC
  31. #define Sign SAFunction20
  32. #define VerifySignature SAFunction21
  33. #define _SetSignature SAFunction22
  34. #endif
  35. #define SIGNATURE_SIZE 64
  36. //
  37. // Bit mask for the internal reserved portion of the bit flags.
  38. //
  39. #define JOB_INTERNAL_FLAG_MASK (0xffff8000)
  40. //
  41. // Values for CJob::m_rgFlags
  42. //
  43. // The upper word of the job flag property is reserved for internal use.
  44. // Lower word (public) values are defined in mstask.h (mstask.idl).
  45. //
  46. // Note that a job can have both JOB_I_FLAG_HAS_TRIGGERS and
  47. // JOB_I_FLAG_NO_VALID_TRIGGERS set. That means the triggers are either unset
  48. // or disabled.
  49. //
  50. #define JOB_I_FLAG_APPNAME_CHANGE (0x00010000)
  51. #define JOB_I_FLAG_SET_ACCOUNT_INFO (0x00020000)
  52. #define JOB_I_FLAG_NO_VALID_TRIGGERS (0x00040000)
  53. #define JOB_I_FLAG_LAST_LAUNCH_FAILED (0x00080000)
  54. #define JOB_I_FLAG_ERROR_IN_LAST_RUN (0x00100000)
  55. #define JOB_I_FLAG_NET_SCHEDULE (0x00200000)
  56. #define JOB_I_FLAG_NO_MORE_RUNS (0x00400000)
  57. //
  58. // The following flags are for determining job validity when the string
  59. // properties and triggers haven't been loaded.
  60. //
  61. #define JOB_I_FLAG_HAS_TRIGGERS (0x00800000)
  62. #define JOB_I_FLAG_HAS_APPNAME (0x01000000)
  63. #define JOB_I_FLAG_HAS_ACCOUNT (0x02000000)
  64. //
  65. // These flags are for job interface communication with the service.
  66. //
  67. #define JOB_I_FLAG_RUN_NOW (0x04000000)
  68. #define JOB_I_FLAG_ABORT_NOW (0x08000000)
  69. //
  70. // The following two flags are used to prevent unnecessary Wait List rebuilds.
  71. // CheckDir is called whenever there are changes made to job file objects.
  72. // If a change is caused by the service (when it updates the run status of a
  73. // job), we do not want the wait list to be rebuilt. If a change is caused by
  74. // a scheduler client, we do not want the wait list to be rebuilt *unless* the
  75. // change affects the job's run-ability. Those things that affect the run-
  76. // ability are run-time (triggers), adding or deleting an app name, or
  77. // toggling the disabled flag. We need both flags because we cannot control
  78. // the order that clients call the property and trigger modification methods.
  79. // See additonal comments about this in SaveP in persist.cxx.
  80. //
  81. #define JOB_I_FLAG_RUN_PROP_CHANGE (0x10000000)
  82. #define JOB_I_FLAG_NO_RUN_PROP_CHANGE (0x20000000)
  83. //
  84. // The top two bits are used as non-persistent dirty state flags.
  85. //
  86. #define JOB_DIRTY_FLAG_MASK (0xC0000000)
  87. #define JOB_I_FLAG_PROPERTIES_DIRTY (0x40000000)
  88. #define JOB_I_FLAG_TRIGGERS_DIRTY (0x80000000)
  89. #define JOB_I_FLAG_MISSED (0x00008000)
  90. //
  91. // Mask of non-persisted job flags. Masked off on save.
  92. //
  93. #define NON_PERSISTED_JOB_FLAGS (JOB_DIRTY_FLAG_MASK | \
  94. JOB_I_FLAG_SET_ACCOUNT_INFO)
  95. //
  96. // Values for CTrigger::m_rgFlags
  97. //
  98. // The upper word of the trigger flag member is reserved for internal use.
  99. // Lower word (public) values are defined in mstask.h (mstask.idl).
  100. //
  101. #define JOB_TRIGGER_I_FLAG_NOT_SET (0x00010000)
  102. #define JOB_TRIGGER_I_FLAG_DURATION_AS_TIME (0x00020000)
  103. //
  104. // Values for CJob::SaveP flOptions parameter
  105. //
  106. #define SAVEP_VARIABLE_LENGTH_DATA (0x00000001)
  107. #define SAVEP_RUNNING_INSTANCE_COUNT (0x00000002)
  108. #define SAVEP_PRESERVE_NET_SCHEDULE (0x00000004)
  109. //
  110. // This macro can be used within methods of CJob
  111. //
  112. #define DELETE_CJOB_FIELD(m_pField) \
  113. if (!m_MainBlock.Contains(m_pField)) \
  114. { \
  115. delete [] (m_pField); \
  116. } \
  117. m_pField = NULL;
  118. // else it will be deleted by m_MainBlock.Set() or ~m_MainBlock()
  119. //+----------------------------------------------------------------------------
  120. //
  121. // Class: CTrigger
  122. //
  123. // Purpose: Trigger object - represents a job run time repetition period
  124. //
  125. //-----------------------------------------------------------------------------
  126. class CTrigger : public ITaskTrigger
  127. {
  128. friend CJob;
  129. friend CSchedule;
  130. public:
  131. CTrigger(WORD iTrigger, CJob * pJob);
  132. ~CTrigger(void);
  133. // IUnknown methods
  134. STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject);
  135. STDMETHOD_(ULONG, AddRef)(void);
  136. STDMETHOD_(ULONG, Release)(void);
  137. // ITaskTrigger methods
  138. STDMETHOD(SetTrigger)(const PTASK_TRIGGER pTrigger);
  139. STDMETHOD(GetTrigger)(PTASK_TRIGGER pTrigger);
  140. STDMETHOD(GetTriggerString)(LPWSTR * ppwszTrigger);
  141. private:
  142. CJob * m_pJob; // Parent job object.
  143. WORD m_iTrigger; // TASK_TRIGGER index.
  144. ULONG m_cReferences;
  145. };
  146. //+----------------------------------------------------------------------------
  147. //
  148. // Class: CInputBuffer
  149. //
  150. // Synopsis: Used by CJob::LoadP to parse a buffer containing the contents
  151. // of a task file. Using this class is less bug-prone than
  152. // using two pointer variables.
  153. // BOOL methods return FALSE on buffer overrun.
  154. //
  155. //-----------------------------------------------------------------------------
  156. class CInputBuffer
  157. {
  158. private:
  159. const BYTE * _pCurrent; // Current position in buffer
  160. const BYTE * const _pEnd; // First invalid position in buffer
  161. public:
  162. CInputBuffer(const BYTE * pCurrent, const BYTE * pEnd)
  163. : _pCurrent(pCurrent), _pEnd(pEnd) { }
  164. BYTE * CurrentPosition()
  165. { return (BYTE *) _pCurrent; }
  166. BOOL Advance(DWORD cb)
  167. { _pCurrent += cb; return (_pCurrent <= _pEnd); }
  168. BOOL Read(void * pDest, DWORD cb)
  169. {
  170. if (_pCurrent + cb <= _pEnd)
  171. {
  172. CopyMemory(pDest, _pCurrent, cb);
  173. _pCurrent += cb;
  174. return TRUE;
  175. }
  176. else
  177. {
  178. return FALSE;
  179. }
  180. }
  181. };
  182. //+----------------------------------------------------------------------------
  183. //
  184. // Class: CHeapBlock
  185. //
  186. // Synopsis: Variable-length properties of CJob that are read by LoadP
  187. // are held in a single heap block, the original block which
  188. // the task file was read from disk into, as long as they are
  189. // not dirtied. If any one is dirtied a separate heap block
  190. // is allocated for it. This class helps manage the original
  191. // heap block.
  192. //
  193. //-----------------------------------------------------------------------------
  194. class CHeapBlock
  195. {
  196. private:
  197. BYTE * _pStart; // Start of the heap block
  198. const BYTE * _pEnd; // First byte past the end of the heap block
  199. public:
  200. CHeapBlock() : _pStart(NULL), _pEnd(NULL) { }
  201. ~CHeapBlock() { delete [] _pStart; }
  202. void Set(BYTE * pStart, DWORD dwSize)
  203. {
  204. delete [] _pStart;
  205. _pStart = pStart;
  206. _pEnd = _pStart + dwSize;
  207. }
  208. BOOL Contains(void * p)
  209. { return (_pStart <= (BYTE *)p && (BYTE *)p < _pEnd); }
  210. };
  211. typedef struct _FIXDLENDATA {
  212. WORD wVersion;
  213. WORD wFileObjVer;
  214. UUID uuidJob;
  215. WORD wAppNameLenOffset;
  216. WORD wTriggerOffset;
  217. WORD wErrorRetryCount;
  218. WORD wErrorRetryInterval;
  219. WORD wIdleDeadline;
  220. WORD wIdleWait;
  221. DWORD dwPriority;
  222. DWORD dwMaxRunTime;
  223. HRESULT ExitCode;
  224. HRESULT hrStatus;
  225. DWORD rgFlags;
  226. SYSTEMTIME stMostRecentRunTime;
  227. } FIXDLEN_DATA, * PFIXDLEN_DATA;
  228. typedef struct _TASKRESERVED1 {
  229. HRESULT hrStartError;
  230. DWORD rgTaskFlags;
  231. } TASKRESERVED1, * PTASKRESERVED1;
  232. typedef struct _JOB_ACCOUNT_INFO {
  233. WCHAR * pwszAccount;
  234. WCHAR * pwszPassword;
  235. } JOB_ACCOUNT_INFO, * PJOB_ACCOUNT_INFO;
  236. //+----------------------------------------------------------------------------
  237. //
  238. // Class: CJob
  239. //
  240. // Purpose: Job object
  241. //
  242. //-----------------------------------------------------------------------------
  243. class CJob : public ITask, public IPersistFile, public IProvideTaskPage
  244. {
  245. friend CTrigger;
  246. friend CJobCF;
  247. friend CSchedule;
  248. friend CSchedWorker;
  249. public:
  250. CJob();
  251. ~CJob();
  252. // IUnknown methods
  253. STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject);
  254. STDMETHOD_(ULONG, AddRef)(void);
  255. STDMETHOD_(ULONG, Release)(void);
  256. // ITask methods
  257. STDMETHOD(Run)(void);
  258. STDMETHOD(Terminate)(void);
  259. STDMETHOD(EditWorkItem)(HWND hParent, DWORD dwReserved);
  260. STDMETHOD(CreateTrigger)(WORD * piNewTrigger, ITaskTrigger ** ppTrigger);
  261. STDMETHOD(DeleteTrigger)(WORD iTrigger);
  262. STDMETHOD(GetTriggerCount)(WORD * pwCount);
  263. STDMETHOD(GetTrigger)(WORD iTrigger, ITaskTrigger ** ppTrigger);
  264. STDMETHOD(GetTriggerString)(WORD iTrigger, LPWSTR * ppwszTrigger);
  265. STDMETHOD(GetRunTimes)(const LPSYSTEMTIME pstBegin,
  266. const LPSYSTEMTIME pstEnd,
  267. WORD * pwCount, LPSYSTEMTIME * rgstJobTimes);
  268. // ITask properties
  269. STDMETHOD(SetApplicationName)(LPCWSTR pwszApplicationName);
  270. STDMETHOD(GetApplicationName)(LPWSTR * ppwszApplicationName);
  271. STDMETHOD(SetParameters)(LPCWSTR pwszParameters);
  272. STDMETHOD(GetParameters)(LPWSTR * ppwszParameters);
  273. STDMETHOD(SetWorkingDirectory)(LPCWSTR pwszWorkingDirectory);
  274. STDMETHOD(GetWorkingDirectory)(LPWSTR * ppwszWorkingDirectory);
  275. STDMETHOD(SetAccountInformation)(LPCWSTR pwszAccountName,
  276. LPCWSTR pwszPassword);
  277. STDMETHOD(GetAccountInformation)(LPWSTR * ppwszAccountName);
  278. STDMETHOD(SetComment)(LPCWSTR pwszComment);
  279. STDMETHOD(GetComment)(LPWSTR * ppwszComment);
  280. STDMETHOD(SetPriority)(DWORD dwPriority);
  281. STDMETHOD(GetPriority)(DWORD * pdwPriority);
  282. STDMETHOD(SetMaxRunTime)(DWORD dwMaxRunTime);
  283. STDMETHOD(GetMaxRunTime)(DWORD * pdwMaxRunTime);
  284. STDMETHOD(SetIdleWait)(WORD wIdleMinutes, WORD wDeadlineMinutes);
  285. STDMETHOD(GetIdleWait)(WORD * pwIdleMinutes, WORD * pwDeadlineMinutes);
  286. STDMETHOD(SetErrorRetryCount)(WORD wRetryCount);
  287. STDMETHOD(GetErrorRetryCount)(WORD * pwRetryCount);
  288. STDMETHOD(SetErrorRetryInterval)(WORD wRetryInterval);
  289. STDMETHOD(GetErrorRetryInterval)(WORD * pwRetryInterval);
  290. STDMETHOD(SetFlags)(DWORD dwJobFlags);
  291. STDMETHOD(GetFlags)(DWORD * pdwJobFlags);
  292. STDMETHOD(SetTaskFlags)(DWORD dwJobFlags);
  293. STDMETHOD(GetTaskFlags)(DWORD * pdwJobFlags);
  294. STDMETHOD(SetWorkItemData)(WORD cbData, BYTE rgbData[]);
  295. STDMETHOD(GetWorkItemData)(PWORD pcbData, PBYTE * prgbData);
  296. STDMETHOD(GetMostRecentRunTime)(SYSTEMTIME * pstLastRun);
  297. STDMETHOD(GetNextRunTime)(SYSTEMTIME * pstNextRun);
  298. STDMETHOD(GetExitCode)(DWORD * pExitCode);
  299. STDMETHOD(GetStatus)(HRESULT * pStatus);
  300. STDMETHOD(SetCreator)(LPCWSTR pwszCreator);
  301. STDMETHOD(GetCreator)(LPWSTR * ppwszCreator);
  302. // IPersist method
  303. STDMETHOD(GetClassID)(CLSID * pClsID);
  304. // IPersistFile methods
  305. STDMETHOD(IsDirty)(void);
  306. STDMETHOD(Load)(LPCOLESTR pwszFileName, DWORD dwMode);
  307. STDMETHOD(Save)(LPCOLESTR pwszFileName, BOOL fRemember);
  308. STDMETHOD(SaveCompleted)(LPCOLESTR pwszFileName);
  309. STDMETHOD(GetCurFile)(LPOLESTR * ppwszFileName);
  310. // IProvideTaskPage method
  311. STDMETHOD(GetPage)(TASKPAGE tpType, BOOL fPersistChanges,
  312. HPROPSHEETPAGE * phPage);
  313. // CJob methods
  314. static CJob * Create(void)
  315. { return (new CJob); }
  316. HRESULT LoadP(LPCTSTR ptszFileName, DWORD dwMode,
  317. BOOL fRemember, BOOL fAllData);
  318. HRESULT SaveP(LPCTSTR ptszFileName, BOOL fRemember,
  319. ULONG flOptions = 0);
  320. HRESULT LoadTriggers(void);
  321. HRESULT UpdateJobState(BOOL fRunning);
  322. HRESULT PostRunUpdate(long ExitCode, BOOL fFinishedOK);
  323. LPCWSTR GetCommand(void) const { return(m_pwszApplicationName); }
  324. LPTSTR GetFileName(void) const { return(m_ptszFileName); }
  325. HRESULT SetTrigger(WORD iTrigger, PTASK_TRIGGER pTrigger);
  326. HRESULT GetTrigger(WORD iTrigger, PTASK_TRIGGER pTrigger);
  327. void GetAllFlags(DWORD * pFlags) {*pFlags = m_rgFlags;}
  328. HRESULT GetRunTimesP(const SYSTEMTIME * pstBegin,
  329. const SYSTEMTIME * pstEnd,
  330. WORD * pCount, WORD cLimit,
  331. CTimeRunList * pRunList,
  332. LPTSTR ptszShortJobName);
  333. void SetStartError(HRESULT hrStartError)
  334. { m_hrStartError = hrStartError; }
  335. #if !defined(_CHICAGO_)
  336. HRESULT Sign(void);
  337. BOOL VerifySignature(void) const;
  338. HRESULT GetAtInfo(PAT_INFO pAt, LPWSTR pwszCommand,
  339. DWORD * pcchCommand);
  340. #endif
  341. BOOL IsFlagSet(DWORD dwBitFlag) {return m_rgFlags & dwBitFlag;}
  342. protected:
  343. void SetTriggersDirty(void);
  344. void SetFlag(DWORD dwBitFlag) {m_rgFlags |= dwBitFlag;}
  345. void ClearFlag(DWORD dwBitFlag) {m_rgFlags &= ~dwBitFlag;}
  346. DWORD GetUserFlags(void)
  347. {return m_rgFlags & ~JOB_INTERNAL_FLAG_MASK;}
  348. BOOL IsStatus(HRESULT hr) {return m_hrStatus == hr;}
  349. void SetStatus(HRESULT hr) {m_hrStatus = hr;}
  350. HRESULT IfStartupJobAddToList(LPTSTR ptszJobName,
  351. CRunList * pRunList,
  352. CIdleRunList * pIdleWaitList);
  353. HRESULT IfLogonJobAddToList(LPTSTR ptszJobName,
  354. CRunList * pRunList,
  355. CIdleRunList * pIdleWaitList);
  356. HRESULT IfIdleJobAddToList(LPTSTR ptszJobName,
  357. CIdleRunList * pRunList);
  358. HRESULT Delete(void);
  359. private:
  360. HRESULT IfEventJobAddToList(TASK_TRIGGER_TYPE Type,
  361. LPCTSTR ptszJobName,
  362. CRunList * pRunList,
  363. CIdleRunList * pIdleWaitList);
  364. void FreeProperties(void);
  365. TASK_TRIGGER * _GetTrigger(WORD iTrigger);
  366. HRESULT _LoadTriggers(HANDLE hFile);
  367. HRESULT _LoadTriggersFromBuffer(CInputBuffer * pBuf);
  368. HRESULT _SaveTriggers(HANDLE hFile);
  369. HRESULT _SetSignature(const BYTE * pbSignature);
  370. // Properties:
  371. CDynamicArray<TASK_TRIGGER> m_Triggers;
  372. WORD m_wVersion;
  373. WORD m_wFileObjVer;
  374. UUID m_uuidJob;
  375. WORD m_wTriggerOffset;
  376. WORD m_wErrorRetryCount;
  377. WORD m_wErrorRetryInterval;
  378. WORD m_cRunningInstances;
  379. WORD m_wIdleWait;
  380. WORD m_wIdleDeadline;
  381. DWORD m_dwPriority;
  382. DWORD m_dwMaxRunTime;
  383. DWORD m_ExitCode;
  384. HRESULT m_hrStatus;
  385. DWORD m_rgFlags;
  386. DWORD m_rgTaskFlags;
  387. SYSTEMTIME m_stMostRecentRunTime;
  388. LPWSTR m_pwszApplicationName; // [*]
  389. LPWSTR m_pwszParameters; // [*]
  390. LPWSTR m_pwszWorkingDirectory; // [*]
  391. LPWSTR m_pwszCreator; // [*]
  392. LPWSTR m_pwszComment; // [*]
  393. LPTSTR m_ptszFileName;
  394. BOOL m_fFileCreated;
  395. PBYTE m_pbTaskData; // [*]
  396. WORD m_cbTaskData;
  397. WORD m_cReserved;
  398. PBYTE m_pbReserved; // [*]
  399. HRESULT m_hrStartError;
  400. #if !defined(_CHICAGO_)
  401. PJOB_ACCOUNT_INFO m_pAccountInfo; // Allocated exclusively in
  402. // the SetAccountInformation member.
  403. PBYTE m_pbSignature; // [*]
  404. #endif // !defined(_CHICAGO_)
  405. CHeapBlock m_MainBlock; // Initially holds properties marked [*]
  406. // State data:
  407. ITypeInfo * m_pIJobTypeInfo;
  408. unsigned long m_cReferences;
  409. CDllRef m_DllRef;
  410. // Static members
  411. static LPWSTR CJob::* const s_StringField[];
  412. };
  413. //+----------------------------------------------------------------------------
  414. //
  415. // Class: CJobCF
  416. //
  417. // Purpose: job object class factory
  418. //
  419. //-----------------------------------------------------------------------------
  420. class CJobCF : public IClassFactory
  421. {
  422. public:
  423. CJobCF();
  424. // IUnknown methods
  425. STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject);
  426. STDMETHOD_(ULONG, AddRef)();
  427. STDMETHOD_(ULONG, Release)();
  428. // IClassFactory methods
  429. STDMETHOD(CreateInstance)(IUnknown *pUnkOuter,
  430. REFIID riid,
  431. void **ppvObject);
  432. STDMETHOD(LockServer)(BOOL fLock);
  433. static IClassFactory * Create(void);
  434. protected:
  435. ~CJobCF();
  436. unsigned long m_uRefs;
  437. CDllRef m_DllRef;
  438. };
  439. #endif // _JOB_CLS_HXX_