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.

1831 lines
42 KiB

  1. //____________________________________________________________________________
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1996.
  5. //
  6. // File: jobidl.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // Notes: For the first release of the scheduling agent, all security
  15. // operations are disabled under Win95, even Win95 to NT.
  16. //
  17. // History: 1/24/1996 RaviR Created
  18. //
  19. //____________________________________________________________________________
  20. #include "..\pch\headers.hxx"
  21. #pragma hdrstop
  22. #include "dbg.h"
  23. #include "macros.h"
  24. #include "..\inc\resource.h"
  25. #include "resource.h"
  26. #include "..\wizard\resource.h"
  27. #include "..\inc\common.hxx"
  28. #include "jobidl.hxx"
  29. #include "sch_cls.hxx" // sched\inc
  30. #include "job_cls.hxx" // sched\inc
  31. #include "misc.hxx" // sched\inc
  32. #include "util.hxx"
  33. #include "..\schedui\schedui.hxx"
  34. #if !defined(_CHICAGO_)
  35. void
  36. SecurityErrorDialog(
  37. HWND hWndOwner,
  38. HRESULT hr);
  39. #endif // !defined(_CHICAGO_)
  40. /////////////////////////////////////////////////////////////////////////////
  41. /////////////////////////////////////////////////////////////////////////////
  42. ////////
  43. //////// CJobID class implementation
  44. ////////
  45. /////////////////////////////////////////////////////////////////////////////
  46. /////////////////////////////////////////////////////////////////////////////
  47. //+--------------------------------------------------------------------------
  48. //
  49. // Member: CJobID::InitToTemplate
  50. //
  51. // Synopsis: Inititialize this to represent a template object in the
  52. // folder.
  53. //
  54. // History: 05-15-1997 DavidMun Created
  55. //
  56. //---------------------------------------------------------------------------
  57. void
  58. CJobID::InitToTemplate()
  59. {
  60. _id = ID_TEMPLATE;
  61. //
  62. // Name offset is at 1 so the first char can serve to make empty app
  63. // name, creator, and path strings.
  64. //
  65. _oCreator = 0;
  66. _oPath = 0;
  67. _oName = 1;
  68. LoadString(g_hInstance,
  69. IDS_TEMPLATE_NAME,
  70. &_cBuf[_oName],
  71. IDJOB_BUFFER_SIZE - 3);
  72. _cb = offsetof(CJobID, _cBuf) +
  73. (_oName + lstrlen(&_cBuf[_oName]) + 1) * sizeof(TCHAR);
  74. // ^^^ pidl size has to include offset into _cBuf
  75. _NullTerminate();
  76. }
  77. //____________________________________________________________________________
  78. //
  79. // Member: CJobID::Load
  80. //
  81. // Arguments: [pszFolderPath] -- IN
  82. // [pszJob] -- IN
  83. //
  84. // Returns: HRESULT.
  85. //____________________________________________________________________________
  86. HRESULT
  87. CJobID::Load(
  88. LPCTSTR pszFolderPath,
  89. LPTSTR pszJob) // job path relative to Jobs folder with .job extension
  90. {
  91. DEBUG_OUT((DEB_USER12,
  92. "[CJobID::Load] <%ws, %ws>\n",
  93. pszFolderPath ? (LPWSTR)pszFolderPath : L"NULL FolderPath",
  94. pszJob));
  95. #if DBG==1
  96. TCHAR * pExt = PathFindExtension(pszJob);
  97. Win4Assert(lstrcmpi(pExt, TSZ_DOTJOB) == 0);
  98. #endif
  99. HRESULT hr = S_OK;
  100. CJob *pJob = NULL;
  101. ZeroMemory(this, sizeof(CJobID));
  102. do
  103. {
  104. //
  105. // Set creation & last write times
  106. //
  107. TCHAR tcFile[MAX_PATH+1];
  108. LPTSTR pFile = tcFile;
  109. if (pszFolderPath != NULL)
  110. {
  111. lstrcpy(tcFile, pszFolderPath);
  112. lstrcat(tcFile, TEXT("\\"));
  113. lstrcat(tcFile, pszJob);
  114. }
  115. else
  116. {
  117. pFile = pszJob;
  118. }
  119. //
  120. // Skip hidden jobs.
  121. //
  122. if (GetFileAttributes(pFile) & FILE_ATTRIBUTE_HIDDEN)
  123. {
  124. return S_FALSE;
  125. }
  126. HANDLE hFile = CreateFile(pFile, GENERIC_READ, FILE_SHARE_READ,
  127. NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  128. if (hFile == INVALID_HANDLE_VALUE)
  129. {
  130. DEBUG_OUT_LASTERROR;
  131. hr = HRESULT_FROM_WIN32(GetLastError());
  132. break;
  133. }
  134. if (GetFileTime(hFile, &_ftCreation, NULL, &_ftLastWrite) == FALSE)
  135. {
  136. CloseHandle(hFile);
  137. DEBUG_OUT_LASTERROR;
  138. hr = HRESULT_FROM_WIN32(GetLastError());
  139. break;
  140. }
  141. CloseHandle(hFile);
  142. //
  143. // Create & load the job
  144. //
  145. hr = ::JFCreateAndLoadCJob(pszFolderPath, pszJob, &pJob);
  146. CHECK_HRESULT(hr);
  147. BREAK_ON_FAIL(hr);
  148. _id = ID_JOB;
  149. ////////////////////////////////////////////////////////////
  150. //
  151. // Extract the properties
  152. //
  153. //
  154. // Get last exit code
  155. //
  156. // The return value from this call is the task's last start error.
  157. //
  158. HRESULT hrLastStart = pJob->GetExitCode(&_dwExitCode);
  159. //
  160. // Get a code to tell what to display in the "Status" column.
  161. // For the purposes of this column the job can be:
  162. // a. missed
  163. // b. failed to start
  164. // c. running
  165. // d. other
  166. //
  167. ULONG ulAllFlags;
  168. pJob->GetAllFlags(&ulAllFlags);
  169. if (ulAllFlags & JOB_I_FLAG_MISSED)
  170. {
  171. _status = ejsMissed;
  172. }
  173. else if (FAILED(hrLastStart))
  174. {
  175. switch(hrLastStart)
  176. {
  177. case HRESULT_FROM_WIN32(ERROR_LOGON_FAILURE):
  178. _status = ejsBadAcct;
  179. break;
  180. case HRESULT_FROM_WIN32(ERROR_ACCOUNT_RESTRICTION):
  181. _status = ejsResAcct;
  182. break;
  183. default:
  184. _status = ejsWouldNotStart;
  185. }
  186. }
  187. else
  188. {
  189. HRESULT hrStatus = 0;
  190. hr = pJob->GetStatus(&hrStatus);
  191. CHECK_HRESULT(hr);
  192. BREAK_ON_FAIL(hr);
  193. switch (hrStatus)
  194. {
  195. case SCHED_S_TASK_RUNNING:
  196. _status = ejsRunning;
  197. break;
  198. case SCHED_S_TASK_NOT_SCHEDULED:
  199. _status = ejsNotScheduled;
  200. break;
  201. }
  202. }
  203. //
  204. // Get last run time
  205. //
  206. hr = pJob->GetMostRecentRunTime(&_stLastRunTime);
  207. CHECK_HRESULT(hr);
  208. BREAK_ON_FAIL(hr);
  209. // ensure wDayOfWeek is 0, else memcmp fails.
  210. _stLastRunTime.wDayOfWeek = 0;
  211. //
  212. // Get next run time
  213. //
  214. hr = pJob->GetNextRunTime(&_stNextRunTime);
  215. CHECK_HRESULT(hr);
  216. BREAK_ON_FAIL(hr);
  217. // ensure wDayOfWeek is 0, else memcmp fails.
  218. _stNextRunTime.wDayOfWeek = 0;
  219. //
  220. // Get the job flags
  221. //
  222. hr = pJob->GetFlags(&_ulJobFlags);
  223. CHECK_HRESULT(hr);
  224. BREAK_ON_FAIL(hr);
  225. //
  226. // Get the first job trigger if any
  227. //
  228. hr = pJob->GetTriggerCount(&_cTriggers);
  229. CHECK_HRESULT(hr);
  230. BREAK_ON_FAIL(hr);
  231. if (_cTriggers > 0)
  232. {
  233. ITaskTrigger * pIJobTrigger = NULL;
  234. hr = pJob->GetTrigger(0, &pIJobTrigger);
  235. CHECK_HRESULT(hr);
  236. BREAK_ON_FAIL(hr);
  237. _sJobTrigger.cbTriggerSize = sizeof(TASK_TRIGGER);
  238. hr = pIJobTrigger->GetTrigger(&_sJobTrigger);
  239. pIJobTrigger->Release();
  240. CHECK_HRESULT(hr);
  241. BREAK_ON_FAIL(hr);
  242. }
  243. else
  244. {
  245. _sJobTrigger.cbTriggerSize = 0;
  246. }
  247. ///////////////////////////////////////////////////////////////////
  248. //
  249. // Fill up the buffer cBuf
  250. //
  251. USHORT cchCurr = 0;
  252. //
  253. // Get the command
  254. //
  255. LPWSTR pwszCommand = NULL;
  256. hr = pJob->GetApplicationName(&pwszCommand);
  257. CHECK_HRESULT(hr);
  258. BREAK_ON_FAIL(hr);
  259. #ifndef UNICODE
  260. hr = UnicodeToAnsi(_cBuf, pwszCommand, MAX_PATH);
  261. CoTaskMemFree(pwszCommand);
  262. BREAK_ON_FAIL(hr);
  263. #else
  264. lstrcpy(_cBuf, pwszCommand);
  265. CoTaskMemFree(pwszCommand);
  266. #endif
  267. DEBUG_OUT((DEB_USER12, "Command = %ws\n", _cBuf));
  268. // update size
  269. cchCurr += lstrlen(_cBuf) + 1;
  270. //
  271. // Get the account name
  272. //
  273. _oCreator = cchCurr;
  274. LPWSTR pwszCreator = NULL;
  275. hr = pJob->GetCreator(&pwszCreator);
  276. CHECK_HRESULT(hr);
  277. BREAK_ON_FAIL(hr);
  278. #if defined(UNICODE)
  279. lstrcpy(&_cBuf[_oCreator], pwszCreator);
  280. CoTaskMemFree(pwszCreator);
  281. #else
  282. hr = UnicodeToAnsi(&_cBuf[_oCreator], pwszCreator, MAX_PATH);
  283. CoTaskMemFree(pwszCreator);
  284. BREAK_ON_FAIL(hr);
  285. #endif
  286. // update size
  287. cchCurr += lstrlen(&_cBuf[_oCreator]) + 1;
  288. //
  289. // Copy the job path
  290. //
  291. _oPath = cchCurr;
  292. if (pszFolderPath == NULL)
  293. {
  294. pszJob = PathFindFileName(pszJob);
  295. }
  296. lstrcpy(&_cBuf[_oPath], pszJob);
  297. TCHAR * ptcPath = &_cBuf[_oPath];
  298. TCHAR * ptcName = PathFindFileName(ptcPath);
  299. TCHAR * ptcExtn = PathFindExtension(ptcName);
  300. if (ptcExtn)
  301. {
  302. *ptcExtn = TEXT('\0');
  303. }
  304. _oName = _oPath + (USHORT)(ptcName - ptcPath) * sizeof(TCHAR);
  305. // update buff size
  306. cchCurr += lstrlen(ptcPath) + 1;
  307. //
  308. // Finaly set the size
  309. //
  310. _cb = offsetof(CJobID, _cBuf) + cchCurr * sizeof(TCHAR);
  311. //
  312. // Ensure that the DWORD at the end is zero, used by ILClone, etc.
  313. //
  314. _NullTerminate();
  315. } while (0);
  316. if (pJob != NULL)
  317. {
  318. pJob->Release();
  319. }
  320. return hr;
  321. }
  322. //____________________________________________________________________________
  323. //
  324. // Member: CJobID::Rename
  325. //
  326. // Synopsis: Loads this object with data from jidIn, except for
  327. // the name which is set to lpszName.
  328. //
  329. // Arguments: [jidIn] -- IN
  330. // [lpszName] -- IN
  331. //
  332. // Returns: HRESULT.
  333. //
  334. // History: 1/25/1996 RaviR Created
  335. //
  336. //____________________________________________________________________________
  337. HRESULT
  338. CJobID::Rename(
  339. CJobID & jidIn,
  340. LPCOLESTR lpszNameIn)
  341. {
  342. ZeroMemory(this, sizeof(CJobID));
  343. CopyMemory(this, &jidIn, jidIn.GetSize());
  344. LPTSTR lpszName = (LPTSTR)lpszNameIn;
  345. #if !defined(UNICODE)
  346. CHAR cBufTemp[MAX_PATH];
  347. HRESULT hr = UnicodeToAnsi(cBufTemp, lpszNameIn, MAX_PATH);
  348. if (FAILED(hr))
  349. {
  350. return hr;
  351. }
  352. lpszName = cBufTemp;
  353. #endif
  354. lstrcpy(&_cBuf[_oName], lpszName);
  355. _cb = offsetof(CJobID, _cBuf) +
  356. (_oName + lstrlen(lpszName) + 1) * sizeof(TCHAR);
  357. _NullTerminate();
  358. return S_OK;
  359. }
  360. //____________________________________________________________________________
  361. //
  362. // Member: CJobID::Clone
  363. //
  364. // Returns: CJobID *
  365. //____________________________________________________________________________
  366. CJobID *
  367. CJobID::Clone(void)
  368. {
  369. CJobID * pjid = (CJobID *) SHAlloc(_cb + sizeof(_cb));
  370. if (pjid)
  371. {
  372. CopyMemory(pjid, this, _cb);
  373. pjid->_NullTerminate();
  374. }
  375. return pjid;
  376. }
  377. #if (DBG == 1)
  378. //+--------------------------------------------------------------------------
  379. //
  380. // Member: CJobID::Validate
  381. //
  382. // Synopsis: Assert if this job idlist object is invalid
  383. //
  384. // History: 12-04-1997 DavidMun Created
  385. //
  386. // Notes: For debugging only.
  387. //
  388. //---------------------------------------------------------------------------
  389. VOID
  390. CJobID::Validate()
  391. {
  392. //
  393. // Expect _cb to have been set to nonzero value
  394. //
  395. Win4Assert(_cb);
  396. Win4Assert(_cb < sizeof(CJobID));
  397. //
  398. // Expect all jobids to have a name. Offset should be nonzero because
  399. // name is not the first string.
  400. //
  401. Win4Assert(_oName < IDJOB_BUFFER_SIZE);
  402. //
  403. // Expect that name is null terminated before the end of the buffer.
  404. //
  405. Win4Assert(_oName + lstrlen(GetName()) < IDJOB_BUFFER_SIZE);
  406. //
  407. // Expect the jobid itself to be null terminated
  408. //
  409. UNALIGNED USHORT *pusNextCB = (UNALIGNED USHORT *)(((BYTE *)this) + _cb);
  410. Win4Assert(_cb + sizeof(USHORT) <= sizeof(CJobID));
  411. Win4Assert(!*pusNextCB);
  412. }
  413. #endif // (DBG == 1)
  414. BOOL
  415. GetLocaleDateTimeString(
  416. SYSTEMTIME* pst,
  417. DWORD dwDateFlags,
  418. DWORD dwTimeFlags,
  419. TCHAR szBuff[],
  420. int cchBuffLen,
  421. LPSHELLDETAILS lpDetails);
  422. //____________________________________________________________________________
  423. //
  424. // Member: CJobID::GetNextRunTimeString
  425. //
  426. // Synopsis: S
  427. //
  428. // Arguments: [tcBuff] -- IN
  429. // [cchBuff] -- IN
  430. // [fForComparison] -- IN
  431. //
  432. // Returns: HRESULT.
  433. //
  434. // History: 4/25/1996 RaviR Created
  435. //
  436. //____________________________________________________________________________
  437. LPTSTR
  438. CJobID::GetNextRunTimeString(
  439. TCHAR tcBuff[],
  440. UINT cchBuff,
  441. BOOL fForComparison,
  442. LPSHELLDETAILS lpDetails)
  443. {
  444. if (this->IsJobNotScheduled() == TRUE)
  445. {
  446. LoadString(g_hInstance, IDS_NEVER, tcBuff, cchBuff);
  447. }
  448. else if (this->IsJobFlagOn(TASK_FLAG_DISABLED) == TRUE)
  449. {
  450. LoadString(g_hInstance, IDS_DISABLED, tcBuff, cchBuff);
  451. }
  452. else if (this->IsTriggerFlagOn(TASK_TRIGGER_FLAG_DISABLED))
  453. {
  454. LoadString(g_hInstance, IDS_TRIGGER_DISABLED, tcBuff, cchBuff);
  455. }
  456. else if (this->GetTriggerType() == TASK_EVENT_TRIGGER_AT_SYSTEMSTART)
  457. {
  458. LoadString(g_hInstance, IDS_ON_STARTUP, tcBuff, cchBuff);
  459. }
  460. else if (this->GetTriggerType() == TASK_EVENT_TRIGGER_AT_LOGON)
  461. {
  462. LoadString(g_hInstance, IDS_ON_LOGON, tcBuff, cchBuff);
  463. }
  464. else if (this->GetTriggerType() == TASK_EVENT_TRIGGER_ON_IDLE)
  465. {
  466. LoadString(g_hInstance, IDS_WHEN_IDLE, tcBuff, cchBuff);
  467. }
  468. else
  469. {
  470. SYSTEMTIME &st = this->GetNextRunTime();
  471. if (st.wYear == 0 || st.wMonth == 0 || st.wDay == 0)
  472. {
  473. LoadString(g_hInstance, IDS_NEVER, tcBuff, cchBuff);
  474. }
  475. else
  476. {
  477. if (fForComparison == TRUE)
  478. {
  479. return NULL;
  480. }
  481. GetLocaleDateTimeString(&st, DATE_SHORTDATE, 0, tcBuff, cchBuff, lpDetails);
  482. }
  483. }
  484. return tcBuff;
  485. }
  486. //____________________________________________________________________________
  487. //
  488. // Function: HDROPFromJobIDList
  489. //
  490. // Synopsis: Create an HDROP for the files in the apjid array.
  491. // Used for CF_HDROP format.
  492. //
  493. // Arguments: [cidl] -- IN
  494. // [apjidl] -- IN
  495. //
  496. // Returns: HDROP
  497. //
  498. // History: 1/31/1996 RaviR Created
  499. //
  500. //____________________________________________________________________________
  501. HDROP
  502. HDROPFromJobIDList(
  503. LPCTSTR pszFolderPath,
  504. UINT cidl,
  505. PJOBID * apjidl)
  506. {
  507. HDROP hMem = 0;
  508. LPDROPFILESTRUCT lpDrop;
  509. DWORD dwSize = 0;
  510. if (cidl == 0)
  511. {
  512. return NULL;
  513. }
  514. TCHAR tcFolder[MAX_PATH];
  515. lstrcpy(tcFolder, pszFolderPath);
  516. lstrcat(tcFolder, TEXT("\\"));
  517. USHORT cbFolderPathLen = (USHORT)(lstrlen(tcFolder) * sizeof(TCHAR));
  518. //
  519. // Walk the list and find out how much space we need.
  520. //
  521. dwSize = sizeof(DROPFILESTRUCT) + sizeof(TCHAR); // size + terminal nul
  522. USHORT * pusPathLen = new USHORT[cidl * 2];
  523. if (pusPathLen == NULL)
  524. {
  525. CHECK_HRESULT(E_OUTOFMEMORY);
  526. return NULL;
  527. }
  528. USHORT * pusExtLen = &pusPathLen[cidl];
  529. for (UINT i=0; i < cidl; i++)
  530. {
  531. pusPathLen[i] = (USHORT)(lstrlen(apjidl[i]->GetPath()) * sizeof(TCHAR));
  532. pusExtLen[i] = (USHORT)((lstrlen(apjidl[i]->GetExtension()) + 1) * sizeof(TCHAR));
  533. dwSize += cbFolderPathLen + pusPathLen[i] + pusExtLen[i];
  534. }
  535. //
  536. // If it's bigger than the struct can hold, then bail.
  537. // TODO: Return an error?
  538. //
  539. if (dwSize > 0x0000ffff)
  540. {
  541. delete [] pusPathLen;
  542. return NULL;
  543. }
  544. //
  545. // Allocate the buffer and fill it in.
  546. //
  547. hMem = (HDROP)GlobalAlloc(GHND, dwSize);
  548. if (hMem == NULL)
  549. {
  550. delete [] pusPathLen;
  551. CHECK_HRESULT(E_OUTOFMEMORY);
  552. return NULL;
  553. }
  554. lpDrop = (LPDROPFILESTRUCT) GlobalLock(hMem);
  555. lpDrop->pFiles = (DWORD)(sizeof(DROPFILESTRUCT));
  556. lpDrop->pt.x = 0;
  557. lpDrop->pt.y = 0;
  558. lpDrop->fNC = FALSE;
  559. #ifdef UNICODE
  560. lpDrop->fWide = TRUE;
  561. #else
  562. lpDrop->fWide = FALSE;
  563. #endif
  564. //
  565. // Fill in the path names.
  566. //
  567. LPBYTE pbTemp = (LPBYTE) ((LPBYTE) lpDrop + lpDrop->pFiles);
  568. for (i=0; i < cidl; i++)
  569. {
  570. CopyMemory(pbTemp, tcFolder, cbFolderPathLen);
  571. pbTemp += cbFolderPathLen;
  572. CopyMemory(pbTemp, apjidl[i]->GetPath(), pusPathLen[i]);
  573. pbTemp += pusPathLen[i];
  574. CopyMemory(pbTemp, apjidl[i]->GetExtension(), pusExtLen[i]);
  575. pbTemp += pusExtLen[i];
  576. }
  577. *((LPTSTR)pbTemp) = TEXT('\0'); // Extra Nul terminate
  578. //
  579. // Unlock the buffer and return it.
  580. //
  581. GlobalUnlock(hMem);
  582. delete [] pusPathLen;
  583. return hMem;
  584. }
  585. //+--------------------------------------------------------------------------
  586. //
  587. // Function: CreateIDListArray
  588. //
  589. // Synopsis: Create shell idlist array in the format required by the
  590. // CFSTR_SHELLIDLIST clipboard format.
  591. //
  592. // Arguments: [pidlFolder] - pidl of tasks folder
  593. // [cidl] - number of elements in [apjidl]
  594. // [apjidl] - array of pointers to idls, each idl
  595. // specifies a .job object.
  596. //
  597. // Returns: Handle to created array, or NULL on error.
  598. //
  599. // History: 05-30-1997 DavidMun Created
  600. //
  601. // Notes: For this format, the first element in the array is an
  602. // absolute idl to a container (the tasks folder), and the
  603. // remainder (each a single .job object) are relative to the
  604. // first.
  605. //
  606. //---------------------------------------------------------------------------
  607. HGLOBAL
  608. CreateIDListArray(
  609. LPCITEMIDLIST pidlFolder,
  610. UINT cidl,
  611. PJOBID *apjidl)
  612. {
  613. TRACE_FUNCTION(CreateIDListArray);
  614. Win4Assert(cidl);
  615. if (cidl == 0)
  616. {
  617. return NULL;
  618. }
  619. HJOBIDA hJobIDA = NULL;
  620. DWORD offset = sizeof(CJobIDA) + sizeof(UINT) * cidl;
  621. DWORD dwSize = offset;
  622. for (UINT i=0; i < cidl ; i++)
  623. {
  624. dwSize += apjidl[i]->GetSize() + 2; // +2 for null list terminator
  625. }
  626. dwSize += ILGetSize(pidlFolder);
  627. hJobIDA = GlobalAlloc(GPTR, dwSize); // This MUST be GlobalAlloc!!!
  628. if (hJobIDA == NULL)
  629. {
  630. CHECK_HRESULT(E_OUTOFMEMORY);
  631. return NULL;
  632. }
  633. PJOBIDA pJobIDA = (PJOBIDA)hJobIDA; // no need to lock
  634. pJobIDA->cidl = cidl; // count doesn't include idl at offset 0,
  635. pJobIDA->aoffset[0] = offset; // which is container
  636. CopyMemory(((LPBYTE)pJobIDA)+offset, pidlFolder, ILGetSize(pidlFolder));
  637. offset += ILGetSize(pidlFolder);
  638. for (i=0; i < cidl ; i++)
  639. {
  640. UINT cbSize = apjidl[i]->GetSize();
  641. pJobIDA->aoffset[i+1] = offset;
  642. CopyMemory(((LPBYTE)pJobIDA)+offset, apjidl[i], cbSize);
  643. offset += cbSize + 2; // +2 to leave null after copied in idl
  644. }
  645. Win4Assert(offset == dwSize);
  646. return hJobIDA;
  647. }
  648. /////////////////////////////////////////////////////////////////////////////
  649. /////////////////////////////////////////////////////////////////////////////
  650. ////////
  651. //////// CJobIDA related functions.
  652. ////////
  653. /////////////////////////////////////////////////////////////////////////////
  654. /////////////////////////////////////////////////////////////////////////////
  655. //____________________________________________________________________________
  656. //
  657. // Function: HJOBIDA_Create
  658. //
  659. // Synopsis: Create an HJOBIDA for the files in the apjid array.
  660. // Used for CF_JOBIDLIST data format.
  661. //
  662. // Arguments: [cidl] -- IN
  663. // [apjidl] -- IN
  664. //
  665. // Returns: HJOBIDA
  666. //
  667. // History: 1/31/1996 RaviR Created
  668. //
  669. //____________________________________________________________________________
  670. HJOBIDA
  671. HJOBIDA_Create(
  672. UINT cidl,
  673. PJOBID * apjidl)
  674. {
  675. if (cidl == 0)
  676. {
  677. return NULL;
  678. }
  679. HJOBIDA hJobIDA = NULL;
  680. DWORD offset = sizeof(CJobIDA) + sizeof(UINT) * (cidl - 1);
  681. DWORD dwSize = offset;
  682. for (UINT i=0; i < cidl ; i++)
  683. {
  684. dwSize += apjidl[i]->GetSize() + 2; // +2 for null list terminator
  685. }
  686. hJobIDA = GlobalAlloc(GPTR, dwSize); // This MUST be GlobalAlloc with
  687. // GPTR!
  688. if (hJobIDA == NULL)
  689. {
  690. CHECK_HRESULT(E_OUTOFMEMORY);
  691. return NULL;
  692. }
  693. PJOBIDA pJobIDA = (PJOBIDA)hJobIDA; // no need to lock
  694. pJobIDA->cidl = cidl;
  695. //
  696. // Note that apjidl[i] reports its true size, which doesn't include the
  697. // extra 0 ulong following it. That null terminator is required, and
  698. // isn't copied into pJobIDA by the CopyMemory, which is using
  699. // apjidl[i]'s reported size.
  700. //
  701. // Since the GPTR ensures zero-initialized memory, and the extra 2
  702. // bytes per jobid has been accounted for in computing dwSize, we can
  703. // get the terminator just by increasing offset by the terminator size
  704. // on each iteration.
  705. //
  706. for (i=0; i < cidl ; i++)
  707. {
  708. UINT cbSize = apjidl[i]->GetSize();
  709. pJobIDA->aoffset[i] = offset;
  710. CopyMemory(((LPBYTE)pJobIDA)+offset, apjidl[i], cbSize);
  711. offset += cbSize + 2;
  712. }
  713. Win4Assert(offset == dwSize);
  714. return hJobIDA;
  715. }
  716. void
  717. HJOBIDA_Free(
  718. HJOBIDA hJobIDA)
  719. {
  720. GlobalFree(hJobIDA); // This MUST be GlobalFree
  721. }
  722. /////////////////////////////////////////////////////////////////////////////
  723. /////////////////////////////////////////////////////////////////////////////
  724. ////////
  725. //////// Functions to clone and free a LPCITEMIDLIST array.
  726. ////////
  727. /////////////////////////////////////////////////////////////////////////////
  728. /////////////////////////////////////////////////////////////////////////////
  729. //____________________________________________________________________________
  730. //
  731. // Function: ILA_Clone
  732. //
  733. // Synopsis: S
  734. //
  735. // Arguments: [cidl] -- IN
  736. // [apidl] -- IN
  737. //
  738. // Returns: LPITEMIDLIST
  739. //
  740. // History: 1/9/1996 RaviR Created
  741. //
  742. //____________________________________________________________________________
  743. LPITEMIDLIST*
  744. ILA_Clone(
  745. UINT cidl,
  746. LPCITEMIDLIST * apidl)
  747. {
  748. TRACE_FUNCTION(ILA_Clone);
  749. LPITEMIDLIST* aNewPidl = new LPITEMIDLIST[cidl];
  750. if (NULL == aNewPidl)
  751. {
  752. return NULL;
  753. }
  754. for (UINT i = 0; i < cidl; i++)
  755. {
  756. aNewPidl[i] = ILClone(apidl[i]);
  757. if (NULL == aNewPidl[i])
  758. {
  759. // delete what we've allocated so far
  760. for (UINT j = 0; j < i; j++)
  761. {
  762. ILFree(aNewPidl[i]);
  763. }
  764. delete[] aNewPidl;
  765. return NULL;
  766. }
  767. }
  768. return aNewPidl;
  769. }
  770. //____________________________________________________________________________
  771. //
  772. // Function: ILA_Free
  773. //
  774. // Synopsis: S
  775. //
  776. // Arguments: [cidl] -- IN
  777. // [apidl] -- IN
  778. //
  779. // Returns: VOID
  780. //
  781. // History: 1/9/1996 RaviR Created
  782. //
  783. //____________________________________________________________________________
  784. VOID
  785. ILA_Free(
  786. UINT cidl,
  787. LPITEMIDLIST * apidl)
  788. {
  789. TRACE_FUNCTION(ILA_Free);
  790. for (UINT i = 0; i < cidl; i++)
  791. {
  792. ILFree(apidl[i]);
  793. }
  794. delete [] apidl;
  795. }
  796. /////////////////////////////////////////////////////////////////////////////
  797. /////////////////////////////////////////////////////////////////////////////
  798. ////////
  799. //////// Functions to access the CJob & CSchedule
  800. ////////
  801. /////////////////////////////////////////////////////////////////////////////
  802. /////////////////////////////////////////////////////////////////////////////
  803. //____________________________________________________________________________
  804. //
  805. // Function: JFGetJobScheduler
  806. //
  807. // Synopsis: S
  808. //
  809. // Arguments: [ppJobScheduler] -- IN
  810. // [ppwszFolderPath] -- IN
  811. //
  812. // Returns: HRESULT
  813. //
  814. // History: 1/25/1996 RaviR Created
  815. //
  816. //____________________________________________________________________________
  817. HRESULT
  818. JFGetJobScheduler(
  819. LPTSTR pszMachine,
  820. ITaskScheduler ** ppJobScheduler,
  821. LPCTSTR *ppszFolderPath)
  822. {
  823. HRESULT hr = S_OK;
  824. CSchedule * pCSchedule = NULL;
  825. do
  826. {
  827. pCSchedule = new CSchedule;
  828. if (pCSchedule == NULL)
  829. {
  830. hr = E_OUTOFMEMORY;
  831. CHECK_HRESULT(hr);
  832. break;
  833. }
  834. hr = pCSchedule->Init();
  835. CHECK_HRESULT(hr);
  836. BREAK_ON_FAIL(hr);
  837. if (pszMachine != NULL)
  838. {
  839. #ifdef UNICODE
  840. hr = pCSchedule->SetTargetComputer(pszMachine);
  841. #else
  842. WCHAR wBuff[MAX_PATH];
  843. hr = AnsiToUnicode(wBuff, pszMachine, MAX_PATH);
  844. CHECK_HRESULT(hr);
  845. BREAK_ON_FAIL(hr);
  846. hr = pCSchedule->SetTargetComputer(wBuff);
  847. #endif
  848. CHECK_HRESULT(hr);
  849. BREAK_ON_FAIL(hr);
  850. }
  851. *ppszFolderPath = pCSchedule->GetFolderPath();
  852. *ppJobScheduler = (ITaskScheduler *)pCSchedule;
  853. } while (0);
  854. if (FAILED(hr) && pCSchedule != NULL)
  855. {
  856. pCSchedule->Release();
  857. }
  858. return hr;
  859. }
  860. //____________________________________________________________________________
  861. //
  862. // Member: CreateAndLoadCJob
  863. //
  864. // Arguments: [pszJob] -- IN
  865. // [ppJob] -- OUT
  866. //
  867. // Returns: HRESULT.
  868. //____________________________________________________________________________
  869. HRESULT
  870. JFCreateAndLoadCJob(
  871. LPCTSTR pszFolderPath,
  872. LPTSTR pszJob, // job path relative to the folder
  873. CJob ** ppJob)
  874. {
  875. TRACE_FUNCTION(CreateAndLoadCJob);
  876. *ppJob = NULL; // init for failure
  877. CJob *pJob = CJob::Create();
  878. if (pJob == NULL)
  879. {
  880. CHECK_HRESULT(E_OUTOFMEMORY);
  881. return E_OUTOFMEMORY;
  882. }
  883. TCHAR buff[MAX_PATH];
  884. LPTSTR pszJobPathTemp = pszJob;
  885. if (pszFolderPath != NULL)
  886. {
  887. lstrcpy(buff, pszFolderPath);
  888. lstrcat(buff, TEXT("\\"));
  889. lstrcat(buff, pszJob);
  890. pszJobPathTemp = buff;
  891. }
  892. HRESULT hr = S_OK;
  893. #if defined(UNICODE)
  894. LPWSTR pwszJobPath = pszJobPathTemp;
  895. #else
  896. WCHAR wcBuff[MAX_PATH];
  897. hr = AnsiToUnicode(wcBuff, pszJobPathTemp, MAX_PATH);
  898. if (FAILED(hr))
  899. {
  900. pJob->Release();
  901. CHECK_HRESULT(hr);
  902. return hr;
  903. }
  904. LPWSTR pwszJobPath = wcBuff;
  905. #endif
  906. DEBUG_OUT((DEB_USER1, "Load Job <%ws>\n", pwszJobPath));
  907. hr = pJob->Load(pwszJobPath, STGM_READWRITE | STGM_SHARE_EXCLUSIVE);
  908. if (FAILED(hr))
  909. {
  910. pJob->Release();
  911. CHECK_HRESULT(hr);
  912. return hr;
  913. }
  914. //
  915. // Success, return the object
  916. //
  917. *ppJob = pJob;
  918. return hr;
  919. }
  920. //+--------------------------------------------------------------------------
  921. //
  922. // Function: JFCreateAndLoadTask
  923. //
  924. // Synopsis: Create an in-memory task object and initialize it from
  925. // [pszJob], returning the ITask interface on the object.
  926. //
  927. // Arguments: [pszFolderPath] - path to tasks folder
  928. // [pszJob] - filename of job
  929. // [ppITask] - filled with ITask interface ptr
  930. //
  931. // Returns: HRESULT
  932. //
  933. // Modifies: *[ppITask]
  934. //
  935. // History: 10-07-1997 DavidMun Created
  936. //
  937. // Notes: Caller must Release returned interface.
  938. //
  939. //---------------------------------------------------------------------------
  940. HRESULT
  941. JFCreateAndLoadTask(
  942. LPCTSTR pszFolderPath,
  943. LPTSTR pszJob, // job path relative to the folder
  944. ITask ** ppITask)
  945. {
  946. TRACE_FUNCTION(CreateAndLoadTask);
  947. HRESULT hr;
  948. CJob *pJob;
  949. hr = JFCreateAndLoadCJob(pszFolderPath, pszJob, &pJob);
  950. if (SUCCEEDED(hr))
  951. {
  952. hr = pJob->QueryInterface(IID_ITask, (void **)ppITask);
  953. pJob->Release();
  954. }
  955. return hr;
  956. }
  957. //____________________________________________________________________________
  958. //
  959. // Function: JFSaveJob
  960. //
  961. // Synopsis: Save task settings to storage via the task's IPersistFile
  962. // interface. Also, if applicable, prompt the user for security
  963. // account information.
  964. //
  965. // Arguments: [hwndOwner] -- Owner window.
  966. // [pIJob] -- Target task object.
  967. // [fSecuritySupported] -- Flag indicating if
  968. // security-specific code
  969. // should be invoked.
  970. // [fTaskAccountChange] -- TRUE, the task account
  971. // information has
  972. // changed.
  973. // [fTaskApplicationChange] -- TRUE, the task
  974. // application has
  975. // changed.
  976. // [fSuppressAccountInformationRequest] -- TRUE, do not prompt
  977. // the user for account
  978. // information.
  979. //
  980. // Returns: HRESULT
  981. //
  982. // History: 4/25/1996 RaviR Created
  983. //
  984. //____________________________________________________________________________
  985. HRESULT
  986. JFSaveJob(
  987. HWND hwndOwner,
  988. ITask * pITask,
  989. BOOL fSecuritySupported,
  990. BOOL fTaskAccountChange,
  991. BOOL fTaskApplicationChange,
  992. BOOL fSuppressAccountInformationRequest)
  993. {
  994. #if defined(_CHICAGO_)
  995. Win4Assert(!fSecuritySupported);
  996. #endif // defined(_CHICAGO_)
  997. #if !defined(_CHICAGO_)
  998. AccountInfo AcctInfo;
  999. #endif // !defined(_CHICAGO_)
  1000. HRESULT hr;
  1001. IPersistFile * pipfTask;
  1002. WCHAR * pwszAccountName = NULL;
  1003. #if !defined(_CHICAGO_)
  1004. BOOL fChangesSaved = FALSE;
  1005. #endif // !defined(_CHICAGO_)
  1006. hr = pITask->QueryInterface(IID_IPersistFile, (void **)&pipfTask);
  1007. if (FAILED(hr))
  1008. {
  1009. return hr;
  1010. }
  1011. #if !defined(_CHICAGO_)
  1012. if (fSecuritySupported)
  1013. {
  1014. InitializeAccountInfo(&AcctInfo);
  1015. //
  1016. // Application change but no corresponding account information change.
  1017. // Launch the set account information dialog in this case.
  1018. //
  1019. if (fTaskApplicationChange && !fTaskAccountChange)
  1020. {
  1021. //
  1022. // Attempt to retreive account information for the set account
  1023. // information dialog. Ignore failures, we would just like to
  1024. // have something to fill in the account name control.
  1025. //
  1026. if (SUCCEEDED(pITask->GetAccountInformation(&pwszAccountName)))
  1027. {
  1028. AcctInfo.pwszAccountName = pwszAccountName;
  1029. }
  1030. goto SetAccountInformationDlg;
  1031. }
  1032. }
  1033. #endif // !defined(_CHICAGO_)
  1034. //
  1035. // Go ahead and save the changes.
  1036. //
  1037. hr = pipfTask->Save(NULL, FALSE);
  1038. #if !defined(_CHICAGO_)
  1039. fChangesSaved = TRUE;
  1040. #endif // !defined(_CHICAGO_)
  1041. #if !defined(_CHICAGO_)
  1042. if (fSecuritySupported)
  1043. {
  1044. if (FAILED(hr))
  1045. {
  1046. if (pipfTask->IsDirty() == S_FALSE)
  1047. {
  1048. //
  1049. // If Save failed, yet the job is no longer dirty, the
  1050. // error is due to a failure setting security information.
  1051. //
  1052. // Let the user know there was a problem. Remap the return
  1053. // code so we don't get further error dialogs.
  1054. //
  1055. CHECK_HRESULT(hr);
  1056. SecurityErrorDialog(hwndOwner, hr);
  1057. hr = S_OK;
  1058. }
  1059. #if DBG == 1
  1060. else
  1061. {
  1062. //
  1063. // Standard persist code failure. Calling page code will
  1064. // put up an error dialog.
  1065. //
  1066. CHECK_HRESULT(hr);
  1067. }
  1068. #endif // DBG == 1
  1069. goto CleanExit;
  1070. }
  1071. if (!fTaskAccountChange)
  1072. {
  1073. //
  1074. // No account information changes. Verify that this job does
  1075. // indeed have account information associated with it.
  1076. //
  1077. hr = pITask->GetAccountInformation(&pwszAccountName);
  1078. if (hr == SCHED_E_ACCOUNT_INFORMATION_NOT_SET)
  1079. {
  1080. //
  1081. // No account information. Launch the set account information
  1082. // dialog.
  1083. //
  1084. hr = S_OK;
  1085. goto SetAccountInformationDlg;
  1086. }
  1087. else if (SUCCEEDED(hr))
  1088. {
  1089. //
  1090. // Done.
  1091. //
  1092. goto CleanExit;
  1093. }
  1094. else
  1095. {
  1096. //
  1097. // In error cases, silently fail. There's nothing we can do
  1098. // about it other than confuse the user. Remapping the return
  1099. // code so the calling page code doesn't put up an error
  1100. // dialog.
  1101. //
  1102. CHECK_HRESULT(hr);
  1103. hr = S_OK;
  1104. goto CleanExit;
  1105. }
  1106. }
  1107. else if (fTaskApplicationChange && fTaskAccountChange)
  1108. {
  1109. //
  1110. // Fetch cached account information from the job object for
  1111. // the pending set account information dialog. Silently fail
  1112. // in an error case.
  1113. //
  1114. hr = pITask->GetAccountInformation(&pwszAccountName);
  1115. Win4Assert(hr != SCHED_E_ACCOUNT_INFORMATION_NOT_SET);
  1116. if (FAILED(hr) || hr == S_FALSE)
  1117. {
  1118. //
  1119. // The information is cached. This would fail for no
  1120. // reason other than insufficient memory.
  1121. //
  1122. // Though, did we goof?
  1123. //
  1124. CHECK_HRESULT(hr);
  1125. hr = S_OK;
  1126. goto CleanExit;
  1127. }
  1128. AcctInfo.pwszAccountName = pwszAccountName;
  1129. }
  1130. else
  1131. {
  1132. //
  1133. // Done.
  1134. //
  1135. goto CleanExit;
  1136. }
  1137. }
  1138. else
  1139. {
  1140. CHECK_HRESULT(hr);
  1141. goto CleanExit;
  1142. }
  1143. SetAccountInformationDlg:
  1144. //
  1145. // Should've arrived here only for security reasons.
  1146. //
  1147. Win4Assert(fSecuritySupported);
  1148. //
  1149. // Can only arrive at this point if the user must specify security
  1150. // account information.
  1151. //
  1152. // Launch the set account information dialog.
  1153. //
  1154. if (!fSuppressAccountInformationRequest)
  1155. {
  1156. LaunchSetAccountInformationDlg(hwndOwner, &AcctInfo);
  1157. //
  1158. // Check if the data is dirty. On dialog entry, the password is set
  1159. // to the global empty string. If the password ptr still equals this,
  1160. // then the user didn't change the password (e.g. the user canceled
  1161. // the dialog).
  1162. //
  1163. if (AcctInfo.pwszAccountName != NULL &&
  1164. AcctInfo.pwszPassword != tszEmpty)
  1165. {
  1166. //
  1167. // Reset the account information and persist the changes.
  1168. //
  1169. hr = pITask->SetAccountInformation(AcctInfo.pwszAccountName,
  1170. AcctInfo.pwszPassword);
  1171. fChangesSaved = FALSE;
  1172. if (FAILED(hr))
  1173. {
  1174. goto CleanExit;
  1175. }
  1176. }
  1177. }
  1178. if (!fChangesSaved)
  1179. {
  1180. CWaitCursor WaitCursor;
  1181. hr = pipfTask->Save(NULL, FALSE);
  1182. if (FAILED(hr) && pipfTask->IsDirty() == S_FALSE)
  1183. {
  1184. //
  1185. // Similar check as above. General save succeeded but the attempt
  1186. // to set security information failed. Let the user know there
  1187. // was a problem and remap the return code so we don't get
  1188. // further dialogs.
  1189. //
  1190. SecurityErrorDialog(hwndOwner, hr);
  1191. hr = S_OK;
  1192. }
  1193. #if DBG == 1
  1194. else
  1195. {
  1196. CHECK_HRESULT(hr);
  1197. }
  1198. #endif // DBG == 1
  1199. }
  1200. #endif // !defined(_CHICAGO_)
  1201. #if !defined(_CHICAGO_)
  1202. CleanExit:
  1203. #endif // !defined(_CHICAGO_)
  1204. pipfTask->Release();
  1205. #if !defined(_CHICAGO_)
  1206. if (fSecuritySupported)
  1207. {
  1208. ResetAccountInfo(&AcctInfo);
  1209. }
  1210. #endif // !defined(_CHICAGO_)
  1211. return hr;
  1212. }
  1213. #if !defined(_CHICAGO_)
  1214. //____________________________________________________________________________
  1215. //
  1216. // Function: SecurityErrorDialog
  1217. //
  1218. // Synopsis: Map the error to a hopefully friendly & informative dialog.
  1219. //
  1220. // Arguments: [hWndOwner] -- Parent window handle.
  1221. // [hr] -- Security error to map.
  1222. //
  1223. // Returns: None.
  1224. //
  1225. // Notes: None.
  1226. //
  1227. //____________________________________________________________________________
  1228. void
  1229. SecurityErrorDialog(
  1230. HWND hWndOwner,
  1231. HRESULT hr)
  1232. {
  1233. int idsErrorMessage;
  1234. UINT idsHelpHint;
  1235. idsErrorMessage = IERR_SECURITY_WRITE_ERROR;
  1236. if (hr == SCHED_E_ACCOUNT_NAME_NOT_FOUND)
  1237. {
  1238. idsHelpHint = IDS_HELP_HINT_INVALID_ACCT;
  1239. }
  1240. else if (hr == SCHED_E_ACCOUNT_DBASE_CORRUPT)
  1241. {
  1242. idsHelpHint = IDS_HELP_HINT_DBASE_CORRUPT;
  1243. }
  1244. else if (hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED))
  1245. {
  1246. idsHelpHint = IDS_HELP_HINT_ACCESS_DENIED;
  1247. }
  1248. else if (hr == SCHED_E_SERVICE_NOT_RUNNING ||
  1249. HRESULT_FACILITY(hr) == FACILITY_RPC)
  1250. {
  1251. idsHelpHint = IDS_HELP_HINT_SEC_GENERAL;
  1252. }
  1253. else
  1254. {
  1255. //
  1256. // No help hint for unexpected errors.
  1257. //
  1258. idsHelpHint = 0;
  1259. }
  1260. //
  1261. // Put up the error dialog.
  1262. //
  1263. SchedUIErrorDialog(hWndOwner, idsErrorMessage, hr, idsHelpHint);
  1264. }
  1265. #endif // !defined(_CHICAGO_)
  1266. //____________________________________________________________________________
  1267. //
  1268. // Function: JFGetAppNameForTask
  1269. //
  1270. // Synopsis: S
  1271. //
  1272. // Arguments: [path] -- IN
  1273. // [pszAppName] -- IN
  1274. // [cchAppName] -- IN
  1275. //
  1276. // Returns: HRESULT
  1277. //
  1278. // History: 4/25/1996 RaviR Created
  1279. //
  1280. //____________________________________________________________________________
  1281. HRESULT
  1282. JFGetAppNameForTask(
  1283. LPCTSTR pszTask, // Full path
  1284. LPTSTR pszAppName,
  1285. UINT cchAppName)
  1286. {
  1287. TRACE_FUNCTION(JFGetAppNameForTask);
  1288. HRESULT hr = S_OK;
  1289. CJob *pJob = CJob::Create();
  1290. if (pJob == NULL)
  1291. {
  1292. CHECK_HRESULT(E_OUTOFMEMORY);
  1293. return E_OUTOFMEMORY;
  1294. }
  1295. hr = pJob->LoadP(pszTask, 0, FALSE, FALSE);
  1296. CHECK_HRESULT(hr);
  1297. if (SUCCEEDED(hr))
  1298. {
  1299. LPWSTR pwszCommand = NULL;
  1300. hr = pJob->GetApplicationName(&pwszCommand);
  1301. CHECK_HRESULT(hr);
  1302. if (SUCCEEDED(hr))
  1303. {
  1304. #ifdef UNICODE
  1305. lstrcpy(pszAppName, pwszCommand);
  1306. DEBUG_OUT((DEB_USER1, "JFGetAppNameForTask -> %ws\n", pszAppName));
  1307. #else
  1308. hr = UnicodeToAnsi(pszAppName, pwszCommand, cchAppName);
  1309. #endif
  1310. CoTaskMemFree(pwszCommand);
  1311. }
  1312. }
  1313. pJob->Release();
  1314. return hr;
  1315. }
  1316. BOOL
  1317. IsAScheduleObject(
  1318. TCHAR szFile[])
  1319. {
  1320. if( NULL == szFile )
  1321. {
  1322. return FALSE;
  1323. }
  1324. LPTSTR pszName = PathFindFileName(szFile);
  1325. LPTSTR pszExt = PathFindExtension(pszName);
  1326. if (lstrcmpi(pszExt, TSZ_DOTJOB) != 0)
  1327. // && (lstrcmpi(pszExt, g_szDotQue) != 0)
  1328. {
  1329. return FALSE;
  1330. }
  1331. return TRUE;
  1332. }
  1333. //____________________________________________________________________________
  1334. //
  1335. // Function: JFCopyJob
  1336. //
  1337. // Synopsis: S
  1338. //
  1339. // Arguments: [hwndOwner] -- IN
  1340. // [szFileFrom] -- IN
  1341. // [pszFolderPath] -- IN
  1342. // [fMove] -- IN
  1343. //
  1344. // Returns: HRESULT
  1345. //
  1346. // History: 2/2/1996 RaviR Created
  1347. //
  1348. //____________________________________________________________________________
  1349. HRESULT
  1350. JFCopyJob(
  1351. HWND hwndOwner,
  1352. TCHAR szFileFrom[],
  1353. LPCTSTR pszFolderPath,
  1354. BOOL fMove)
  1355. {
  1356. HRESULT hr = S_OK;
  1357. ITask * pJob = NULL;
  1358. LPTSTR pszName = PathFindFileName(szFileFrom);
  1359. hr = JFCreateAndLoadTask(NULL, szFileFrom, &pJob);
  1360. if (FAILED(hr))
  1361. {
  1362. if (hr == HRESULT_FROM_WIN32(ERROR_INVALID_DATA))
  1363. {
  1364. SchedUIErrorDialog(hwndOwner, IERR_INVALID_DATA, pszName);
  1365. }
  1366. return hr;
  1367. }
  1368. else
  1369. {
  1370. pJob->Release();
  1371. }
  1372. TCHAR szFileTo[MAX_PATH+1];
  1373. lstrcpy(szFileTo, pszFolderPath);
  1374. SHFILEOPSTRUCT fo = {hwndOwner, (fMove ? FO_MOVE : FO_COPY), szFileFrom,
  1375. szFileTo, FOF_ALLOWUNDO, FALSE, NULL, NULL};
  1376. // Make sure we have double trailing NULL!
  1377. *(szFileFrom + lstrlen(szFileFrom) + 1) = TEXT('\0');
  1378. if ((SHFileOperation(&fo) !=0) || fo.fAnyOperationsAborted == TRUE)
  1379. {
  1380. hr = E_FAIL;
  1381. CHECK_HRESULT(hr);
  1382. return hr;
  1383. }
  1384. //SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_PATH, szFileFrom, szFileTo);
  1385. return hr;
  1386. }
  1387. //____________________________________________________________________________
  1388. //
  1389. // Function: GetTriggerStringFromTrigger
  1390. //
  1391. // Synopsis: S
  1392. //
  1393. // Arguments: [pJobTrigger] -- IN
  1394. // [psTrigger] -- IN
  1395. // [cchTrigger] -- IN
  1396. //
  1397. // Returns: HRESULT
  1398. //____________________________________________________________________________
  1399. HRESULT
  1400. GetTriggerStringFromTrigger(
  1401. TASK_TRIGGER * pJobTrigger,
  1402. LPTSTR psTrigger,
  1403. UINT cchTrigger,
  1404. LPSHELLDETAILS lpDetails)
  1405. {
  1406. HRESULT hr = S_OK;
  1407. LPWSTR pwsz = NULL;
  1408. if (pJobTrigger->cbTriggerSize > 0)
  1409. {
  1410. hr = ::StringFromTrigger(pJobTrigger, &pwsz, lpDetails);
  1411. CHECK_HRESULT(hr);
  1412. if (SUCCEEDED(hr))
  1413. {
  1414. #if defined(UNICODE)
  1415. lstrcpy(psTrigger, pwsz);
  1416. #else
  1417. hr = UnicodeToAnsi(psTrigger, pwsz, cchTrigger);
  1418. #endif
  1419. CoTaskMemFree(pwsz);
  1420. }
  1421. }
  1422. else
  1423. {
  1424. LoadString(g_hInstance, IDS_JOB_NOT_SCHEDULED, psTrigger, cchTrigger);
  1425. }
  1426. return hr;
  1427. }
  1428. /////////////////////////////////////////////////////////////////////////////
  1429. /////////////////////////////////////////////////////////////////////////////
  1430. ////////
  1431. //////// Misc functions.
  1432. ////////
  1433. /////////////////////////////////////////////////////////////////////////////
  1434. /////////////////////////////////////////////////////////////////////////////
  1435. LPITEMIDLIST *
  1436. SHIDLFromJobIDL(
  1437. UINT cidl,
  1438. PJOBID * apjidl)
  1439. {
  1440. LPITEMIDLIST * apidlOut = (LPITEMIDLIST *)SHAlloc(
  1441. sizeof(LPITEMIDLIST) * cidl);
  1442. if (apidlOut)
  1443. {
  1444. for (UINT i=0; i < cidl; i++)
  1445. {
  1446. apidlOut[i] = ILCreateFromPath(apjidl[i]->GetPath());
  1447. if (apidlOut[i] == NULL)
  1448. {
  1449. break;
  1450. }
  1451. }
  1452. if (i < cidl) // => memory error
  1453. {
  1454. while (i--)
  1455. {
  1456. ILFree(apidlOut[i]);
  1457. }
  1458. SHFree(apidlOut);
  1459. apidlOut = NULL;
  1460. }
  1461. }
  1462. #if DBG==1
  1463. if (apidlOut == NULL)
  1464. {
  1465. CHECK_HRESULT(E_OUTOFMEMORY);
  1466. }
  1467. #endif
  1468. return apidlOut;
  1469. }