Leaked source code of windows server 2003
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.

943 lines
22 KiB

  1. //____________________________________________________________________________
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1996.
  5. //
  6. // File: menu.hxx
  7. //
  8. // Contents: Declaration of CJobsCM, implementing IContextMenu
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 1/4/1996 RaviR Created
  15. //
  16. //____________________________________________________________________________
  17. #include "..\pch\headers.hxx"
  18. #pragma hdrstop
  19. #include "dbg.h"
  20. #include "macros.h"
  21. #include <misc.hxx> // ARRAY_LEN
  22. #include "policy.hxx"
  23. #include "resource.h"
  24. #include "jobidl.hxx"
  25. #include "util.hxx"
  26. #include "dll.hxx"
  27. #include "..\schedui\schedui.hxx"
  28. #include "..\schedui\dlg.hxx"
  29. #include "..\wizard\wizpage.hxx"
  30. #include "..\wizard\taskwiz.hxx"
  31. //
  32. // extern
  33. //
  34. extern HINSTANCE g_hInstance;
  35. HRESULT
  36. JFGetDataObject(
  37. LPCTSTR pszFolderPath,
  38. LPCITEMIDLIST pidlFolder,
  39. UINT cidl,
  40. LPCITEMIDLIST * apidl,
  41. BOOL fCut,
  42. LPVOID * ppvObj);
  43. HRESULT
  44. JFOpenPropSheet(
  45. LPDATAOBJECT pdtobj,
  46. LPTSTR pszCaption);
  47. HRESULT
  48. GetSchSvcState(
  49. DWORD &dwCurrState);
  50. HRESULT
  51. StartScheduler(void);
  52. HRESULT
  53. PauseScheduler(
  54. BOOL fPause);
  55. BOOL
  56. UserCanChangeService(
  57. LPCTSTR ptszServer);
  58. HRESULT
  59. PromptForServiceStart(
  60. HWND hwnd);
  61. //____________________________________________________________________________
  62. //
  63. // Class: CJobsCM
  64. //
  65. // Purpose: Provide IContextMenu interface to Job Folder objects.
  66. //
  67. // History: 1/24/1996 RaviR Created
  68. //____________________________________________________________________________
  69. class CJobsCM : public IContextMenu
  70. {
  71. public:
  72. CJobsCM(
  73. HWND hwnd,
  74. ITaskScheduler *pScheduler,
  75. LPCTSTR ptszMachine);
  76. HRESULT
  77. InitInstance(
  78. LPCTSTR pszFolderPath,
  79. LPCITEMIDLIST pidlFolder,
  80. UINT cidl,
  81. LPCITEMIDLIST* apidl);
  82. ~CJobsCM();
  83. // IUnknown methods
  84. DECLARE_STANDARD_IUNKNOWN;
  85. // IContextMenu methods
  86. STDMETHOD(QueryContextMenu)(HMENU hmenu, UINT indexMenu, UINT idCmdFirst,
  87. UINT idCmdLast, UINT uFlags);
  88. STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO lpici);
  89. STDMETHOD(GetCommandString)(UINT_PTR idCmd, UINT uType, UINT *pwReserved,
  90. LPSTR pszName, UINT cchMax);
  91. private:
  92. HRESULT _RunJob(CJobID & jid);
  93. HRESULT _AbortJob(CJobID & jid);
  94. HRESULT _DeleteJobs(void);
  95. HRESULT _DisplayJobProperties(HWND hwnd, CJobID & jid);
  96. LPCTSTR m_pszFolderPath;
  97. LPITEMIDLIST m_pidlFolder;
  98. UINT m_cidl;
  99. LPITEMIDLIST * m_apidl;
  100. HWND m_hwnd;
  101. ITaskScheduler * m_pScheduler;
  102. LPCTSTR m_ptszMachine;
  103. };
  104. inline
  105. CJobsCM::CJobsCM(
  106. HWND hwnd,
  107. ITaskScheduler *pScheduler,
  108. LPCTSTR ptszMachine):
  109. m_ulRefs(1),
  110. m_hwnd(hwnd),
  111. m_cidl(0),
  112. m_apidl(NULL),
  113. m_pScheduler(pScheduler),
  114. m_ptszMachine(ptszMachine),
  115. m_pidlFolder(NULL),
  116. m_pszFolderPath(NULL)
  117. {
  118. TRACE(CJobsCM, CJobsCM);
  119. }
  120. //____________________________________________________________________________
  121. //
  122. // Member: CJobsCM::~CJobsCM, Destructor
  123. //
  124. // History: 1/8/1996 RaviR Created
  125. //____________________________________________________________________________
  126. CJobsCM::~CJobsCM()
  127. {
  128. TRACE(CJobsCM, ~CJobsCM);
  129. ILA_Free(m_cidl, m_apidl);
  130. ILFree(m_pidlFolder);
  131. m_cidl = 0;
  132. m_apidl = NULL;
  133. // Don't do a release on pScheduler, since this object never
  134. // increased its ref count.
  135. }
  136. //____________________________________________________________________________
  137. //
  138. // Member: IUnknown methods
  139. //____________________________________________________________________________
  140. IMPLEMENT_STANDARD_IUNKNOWN(CJobsCM);
  141. STDMETHODIMP
  142. CJobsCM::QueryInterface(REFIID riid, LPVOID* ppvObj)
  143. {
  144. if (IsEqualIID(IID_IUnknown, riid) ||
  145. IsEqualIID(IID_IContextMenu, riid))
  146. {
  147. *ppvObj = (IUnknown*)(IContextMenu*) this;
  148. this->AddRef();
  149. return S_OK;
  150. }
  151. *ppvObj = NULL;
  152. return E_NOINTERFACE;
  153. }
  154. //____________________________________________________________________________
  155. //
  156. // Member: CJobsCM::InitInstance
  157. //
  158. // Synopsis: S
  159. //
  160. // Arguments: [cidl] -- IN
  161. // [apidl] -- IN
  162. //
  163. // Returns: HRESULT.
  164. //
  165. // History: 1/8/1996 RaviR Created
  166. //
  167. //____________________________________________________________________________
  168. HRESULT
  169. CJobsCM::InitInstance(
  170. LPCTSTR pszFolderPath,
  171. LPCITEMIDLIST pidlFolder,
  172. UINT cidl,
  173. LPCITEMIDLIST* apidl)
  174. {
  175. TRACE(CJobsCM, InitInstance);
  176. HRESULT hr = S_OK;
  177. m_pszFolderPath = pszFolderPath;
  178. m_cidl = cidl;
  179. m_apidl = ILA_Clone(cidl, apidl);
  180. if (!m_apidl)
  181. {
  182. hr = E_OUTOFMEMORY;
  183. CHECK_HRESULT(hr);
  184. return hr;
  185. }
  186. m_pidlFolder = ILClone(pidlFolder);
  187. if (!m_pidlFolder)
  188. {
  189. ILA_Free(m_cidl, m_apidl);
  190. m_cidl = 0;
  191. m_apidl = NULL;
  192. hr = E_OUTOFMEMORY;
  193. CHECK_HRESULT(hr);
  194. return hr;
  195. }
  196. return S_OK;
  197. }
  198. //____________________________________________________________________________
  199. //
  200. // Member: CJobsCM::QueryContextMenu
  201. //
  202. // Synopsis: Same as IContextMenu::QueryContextMenu
  203. //
  204. // Arguments: [hmenu] -- IN
  205. // [indexMenu] -- IN
  206. // [idCmdFirst] -- IN
  207. // [idCmdLast] -- IN
  208. // [uFlags] -- IN
  209. //
  210. // Returns: STDMETHODIMP
  211. //
  212. // History: 1/8/1996 RaviR Created
  213. //
  214. //____________________________________________________________________________
  215. STDMETHODIMP
  216. CJobsCM::QueryContextMenu(
  217. HMENU hmenu,
  218. UINT indexMenu,
  219. UINT idCmdFirst,
  220. UINT idCmdLast,
  221. UINT uFlags)
  222. {
  223. TRACE(CJobsCM, QueryContextMenu);
  224. DEBUG_OUT((DEB_TRACE, "QueryContextMenu<uFlags=%d>\n", uFlags));
  225. QCMINFO qcm = {hmenu, indexMenu, idCmdFirst, idCmdLast};
  226. BOOL fRunning = FALSE; // selected objects include running object
  227. BOOL fTemplate = FALSE; // selected objects include template object
  228. UINT i;
  229. for (i=0; i < m_cidl; i++)
  230. {
  231. PJOBID pjid = (PJOBID)m_apidl[i];
  232. if (pjid->IsTemplate())
  233. {
  234. fTemplate = TRUE;
  235. }
  236. if (pjid->IsRunning())
  237. {
  238. fRunning = TRUE;
  239. }
  240. }
  241. if (fTemplate)
  242. {
  243. UtMergeMenu(g_hInstance,
  244. POPUP_JOB_TEMPLATE,
  245. 0,
  246. (LPQCMINFO)&qcm);
  247. SetMenuDefaultItem(hmenu, idCmdFirst + CMIDM_OPEN, FALSE);
  248. }
  249. else
  250. {
  251. UtMergeMenu(g_hInstance,
  252. (uFlags & CMF_DVFILE) ? POPUP_JOB_VERBS_ONLY : POPUP_JOB,
  253. 0,
  254. (LPQCMINFO)&qcm);
  255. UINT uEnable = (m_cidl > 1) ? (MF_GRAYED | MF_BYCOMMAND)
  256. : (MF_ENABLED | MF_BYCOMMAND);
  257. EnableMenuItem(hmenu, idCmdFirst + CMIDM_PROPERTIES, uEnable);
  258. uEnable = (fRunning == TRUE) ? (MF_ENABLED | MF_BYCOMMAND)
  259. : (MF_GRAYED | MF_BYCOMMAND);
  260. EnableMenuItem(hmenu, idCmdFirst + CMIDM_ABORT, uEnable);
  261. //
  262. // We are trying to prevent the "RUN" command
  263. // from being available if the job is already running
  264. // -- okay b/c we only permit one running instance at a time
  265. //
  266. // Note, that as in the above (abort enable) we have about
  267. // a second's worth of delay between when we fire off the
  268. // run command and when the service actually updates the
  269. // state of the job object itself, permitting us to make the
  270. // right choice. We've always had this with "End Task" and
  271. // it has so far been okay.
  272. //
  273. uEnable = (fRunning == FALSE) ? (MF_ENABLED | MF_BYCOMMAND)
  274. : (MF_GRAYED | MF_BYCOMMAND);
  275. EnableMenuItem(hmenu, idCmdFirst + CMIDM_RUN, uEnable);
  276. //
  277. // Policy - user can control the ui
  278. //
  279. if (RegReadPolicyKey(TS_KEYPOLICY_DENY_DELETE))
  280. {
  281. // Do not permit the removal of tasks
  282. EnableMenuItem(hmenu, idCmdFirst + CMIDM_DELETE,
  283. (MF_GRAYED | MF_BYCOMMAND));
  284. EnableMenuItem(hmenu, idCmdFirst + CMIDM_CUT,
  285. (MF_GRAYED | MF_BYCOMMAND));
  286. EnableMenuItem(hmenu, idCmdFirst + CMIDM_RENAME,
  287. (MF_GRAYED | MF_BYCOMMAND));
  288. }
  289. if (RegReadPolicyKey(TS_KEYPOLICY_DENY_CREATE_TASK))
  290. {
  291. // Do not allow tasks to be created (new name)
  292. EnableMenuItem(hmenu, idCmdFirst + CMIDM_RENAME,
  293. (MF_GRAYED | MF_BYCOMMAND));
  294. }
  295. if (RegReadPolicyKey(TS_KEYPOLICY_DENY_DRAGDROP))
  296. {
  297. // Prevent any drag-drop type operations/clipboard stuff
  298. EnableMenuItem(hmenu, idCmdFirst + CMIDM_CUT,
  299. (MF_GRAYED | MF_BYCOMMAND));
  300. EnableMenuItem(hmenu, idCmdFirst + CMIDM_COPY,
  301. (MF_GRAYED | MF_BYCOMMAND));
  302. EnableMenuItem(hmenu, idCmdFirst + CMIDM_RENAME,
  303. (MF_GRAYED | MF_BYCOMMAND));
  304. }
  305. if (RegReadPolicyKey(TS_KEYPOLICY_DENY_PROPERTIES))
  306. {
  307. // Do not allow access to property pages
  308. EnableMenuItem(hmenu, idCmdFirst + CMIDM_PROPERTIES,
  309. (MF_GRAYED | MF_BYCOMMAND));
  310. }
  311. if (RegReadPolicyKey(TS_KEYPOLICY_DENY_EXECUTION))
  312. {
  313. // Do not allow users to run or stop a job
  314. EnableMenuItem(hmenu, idCmdFirst + CMIDM_RUN,
  315. (MF_GRAYED | MF_BYCOMMAND));
  316. EnableMenuItem(hmenu, idCmdFirst + CMIDM_ABORT,
  317. (MF_GRAYED | MF_BYCOMMAND));
  318. }
  319. SetMenuDefaultItem(hmenu, idCmdFirst + CMIDM_PROPERTIES, FALSE);
  320. }
  321. return ResultFromShort(qcm.idCmdFirst - idCmdFirst);
  322. }
  323. //____________________________________________________________________________
  324. //
  325. // Member: CJobsCM::InvokeCommand
  326. //
  327. // Synopsis: Same as IContextMenu::InvokeCommand
  328. //
  329. // Arguments: [lpici] -- IN
  330. //
  331. // Returns: STDMETHODIMP
  332. //
  333. // History: 1/8/1996 RaviR Created
  334. //
  335. //____________________________________________________________________________
  336. STDMETHODIMP
  337. CJobsCM::InvokeCommand(
  338. LPCMINVOKECOMMANDINFO lpici)
  339. {
  340. TRACE(CJobsCM, InvokeCommand);
  341. HRESULT hr = S_OK;
  342. UINT i;
  343. UINT idCmd;
  344. if (HIWORD(lpici->lpVerb))
  345. {
  346. // Deal with string commands
  347. PSTR pszCmd = (PSTR)lpici->lpVerb;
  348. if (0 == lstrcmpA(pszCmd, "delete"))
  349. {
  350. idCmd = CMIDM_DELETE;
  351. }
  352. else if (0 == lstrcmpA(pszCmd, "properties"))
  353. {
  354. idCmd = CMIDM_PROPERTIES;
  355. }
  356. else if (0 == lstrcmpA(pszCmd, "cut"))
  357. {
  358. idCmd = CMIDM_CUT;
  359. }
  360. else if (0 == lstrcmpA(pszCmd, "copy"))
  361. {
  362. idCmd = CMIDM_COPY;
  363. }
  364. else if (0 == lstrcmpA(pszCmd, "rename"))
  365. {
  366. idCmd = CMIDM_RENAME;
  367. }
  368. else
  369. {
  370. DEBUG_OUT((DEB_ERROR, "Unprocessed InvokeCommand<%s>\n", pszCmd));
  371. return E_INVALIDARG;
  372. }
  373. }
  374. else
  375. {
  376. idCmd = LOWORD(lpici->lpVerb);
  377. }
  378. switch(idCmd)
  379. {
  380. case CMIDM_DELETE:
  381. {
  382. hr = _DeleteJobs();
  383. break;
  384. }
  385. case CMIDM_PROPERTIES:
  386. Win4Assert(m_cidl == 1);
  387. hr = _DisplayJobProperties(m_hwnd, *((PJOBID)m_apidl[0]));
  388. break;
  389. case CMIDM_CUT:
  390. case CMIDM_COPY:
  391. {
  392. LPDATAOBJECT pdobj = NULL;
  393. hr = JFGetDataObject(m_pszFolderPath,
  394. m_pidlFolder,
  395. m_cidl,
  396. (LPCITEMIDLIST *)m_apidl,
  397. (idCmd == CMIDM_CUT),
  398. (void **)&pdobj);
  399. if (SUCCEEDED(hr))
  400. {
  401. hr = OleSetClipboard(pdobj);
  402. CHECK_HRESULT(hr);
  403. }
  404. pdobj->Release();
  405. if (idCmd == CMIDM_CUT)
  406. {
  407. ShellFolderView_SetClipboard(m_hwnd, DFM_CMD_MOVE);
  408. }
  409. break;
  410. }
  411. case CMIDM_RUN:
  412. {
  413. if (UserCanChangeService(m_ptszMachine))
  414. {
  415. hr = PromptForServiceStart(m_hwnd);
  416. }
  417. if (hr != S_OK)
  418. {
  419. break;
  420. }
  421. for (i=0; i < m_cidl; i++)
  422. {
  423. hr = _RunJob(*((PJOBID)m_apidl[i]));
  424. }
  425. break;
  426. }
  427. case CMIDM_ABORT:
  428. {
  429. for (i=0; i < m_cidl; i++)
  430. {
  431. PJOBID pjid = (PJOBID)m_apidl[i];
  432. if (pjid->IsRunning() == TRUE)
  433. {
  434. hr = _AbortJob(*((PJOBID)m_apidl[i]));
  435. }
  436. }
  437. break;
  438. }
  439. case CMIDM_OPEN:
  440. (void) CTaskWizard::Launch(m_pszFolderPath, m_pidlFolder);
  441. break;
  442. default:
  443. return E_FAIL;
  444. }
  445. return hr;
  446. }
  447. //____________________________________________________________________________
  448. //
  449. // Member: CJobsCM::GetCommandString
  450. //
  451. // Synopsis: Same as IContextMenu::GetCommandString
  452. //
  453. // Arguments: [idCmd] -- IN
  454. // [uType] -- IN
  455. // [pwReserved] -- IN
  456. // [pszName] -- IN
  457. // [cchMax] -- IN
  458. //
  459. // Returns: STDMETHODIMP
  460. //
  461. // History: 1/8/1996 RaviR Created
  462. //
  463. //____________________________________________________________________________
  464. STDMETHODIMP
  465. CJobsCM::GetCommandString(
  466. UINT_PTR idCmd,
  467. UINT uType,
  468. UINT * pwReserved,
  469. LPSTR pszName,
  470. UINT cchMax)
  471. {
  472. TRACE(CJobsCM, GetCommandString);
  473. #if DBG==1
  474. char * aType[] = {"GCS_VERBA", "GCS_HELPTEXTA", "GCS_VALIDATEA", "Unused",
  475. "GCS_VERBW", "GCS_HELPTEXTW", "GCS_VALIDATEW", "UNICODE"};
  476. DEBUG_OUT((DEB_TRACE, "GetCommandString<id,type,name> = <%d, %d, %s>\n",
  477. idCmd, uType, aType[uType]));
  478. #endif // DBG==1
  479. *((LPTSTR)pszName) = TEXT('\0');
  480. if (uType == GCS_HELPTEXT)
  481. {
  482. LoadString(g_hInstance, (UINT)idCmd + IDS_MH_FSIDM_FIRST, (LPTSTR)pszName,
  483. cchMax);
  484. return S_OK;
  485. }
  486. if (uType == GCS_VERB && idCmd == CMIDM_RENAME)
  487. {
  488. // "rename" is language independent
  489. StringCchCopy((LPTSTR)pszName, cchMax, TEXT("rename"));
  490. return S_OK;
  491. }
  492. return E_FAIL;
  493. }
  494. //____________________________________________________________________________
  495. //
  496. // Member: CJobsCM::_RunJob
  497. //
  498. // Arguments: [hwnd] -- IN
  499. // [jid] -- IN
  500. //
  501. // Returns: HRESULT.
  502. //
  503. // History: 1/12/1996 RaviR Created
  504. //
  505. //____________________________________________________________________________
  506. HRESULT
  507. CJobsCM::_RunJob(
  508. CJobID & jid)
  509. {
  510. TRACE(CJobsCM, _RunJob);
  511. ITask * pJob = NULL;
  512. TCHAR tcJob[MAX_PATH +1];
  513. StringCchCopy(tcJob, MAX_PATH +1, jid.GetPath());
  514. StringCchCat(tcJob, MAX_PATH +1, TSZ_DOTJOB);
  515. HRESULT hr = ::JFCreateAndLoadTask(m_pszFolderPath, tcJob, &pJob);
  516. if (SUCCEEDED(hr))
  517. {
  518. hr = pJob->Run();
  519. CHECK_HRESULT(hr);
  520. pJob->Release();
  521. }
  522. return hr;
  523. }
  524. //____________________________________________________________________________
  525. //
  526. // Member: CJobsCM::_AbortJob
  527. //
  528. // Arguments: [hwnd] -- IN
  529. // [jid] -- IN
  530. //
  531. // Returns: HRESULT.
  532. //
  533. // History: 1/12/1996 RaviR Created
  534. //
  535. //____________________________________________________________________________
  536. HRESULT
  537. CJobsCM::_AbortJob(
  538. CJobID & jid)
  539. {
  540. TRACE(CJobsCM, _AbortJob);
  541. ITask * pJob = NULL;
  542. TCHAR tcJob[MAX_PATH +1];
  543. StringCchCopy(tcJob, MAX_PATH +1, jid.GetPath());
  544. StringCchCat(tcJob,MAX_PATH +1, TSZ_DOTJOB);
  545. HRESULT hr = ::JFCreateAndLoadTask(m_pszFolderPath, tcJob, &pJob);
  546. if (SUCCEEDED(hr))
  547. {
  548. hr = pJob->Terminate();
  549. CHECK_HRESULT(hr);
  550. pJob->Release();
  551. }
  552. return hr;
  553. }
  554. //____________________________________________________________________________
  555. //
  556. // Member: CJobsCM::_DeleteJobs
  557. //
  558. // Arguments: [hwnd] -- IN
  559. // [pwszJob] -- IN
  560. //
  561. // Returns: HRESULT.
  562. //
  563. // History: 1/11/1996 RaviR Created
  564. //
  565. //____________________________________________________________________________
  566. HRESULT
  567. CJobsCM::_DeleteJobs(void)
  568. {
  569. TRACE(CJobsCM, _DeleteJobs);
  570. PJOBID pjid = NULL;
  571. UINT cchReqd = 0;
  572. //
  573. // Policy - if DELETE flag set, cannot remove jobs
  574. //
  575. if (RegReadPolicyKey(TS_KEYPOLICY_DENY_DELETE))
  576. {
  577. return E_FAIL;
  578. }
  579. //
  580. // First compute buffer size for pFrom.
  581. //
  582. // Each file full path is composed as:
  583. // FolderPath + \ + job path rel to fldr + extn + null
  584. //
  585. // Only <job path rel to fldr> differs for each. (Assuming extension
  586. // length is always 4 <.job, .que>)
  587. for (UINT i=0; i < m_cidl; i++)
  588. {
  589. pjid = (PJOBID)m_apidl[i];
  590. cchReqd += lstrlen(pjid->GetPath());
  591. }
  592. cchReqd += (lstrlen(m_pszFolderPath) + 1 + ARRAY_LEN(TSZ_DOTJOB)) *
  593. m_cidl;
  594. // one for the extra null at the end
  595. ++cchReqd;
  596. LPTSTR pFrom = new TCHAR[cchReqd];
  597. if (pFrom == NULL)
  598. {
  599. CHECK_HRESULT(E_OUTOFMEMORY);
  600. return E_OUTOFMEMORY;
  601. }
  602. UINT ufldrPathLen = lstrlen(m_pszFolderPath);
  603. LPTSTR pCur = pFrom;
  604. for (i=0; i < m_cidl; i++)
  605. {
  606. pjid = (PJOBID)m_apidl[i];
  607. StringCchCopy(pCur, cchReqd - (pCur -pFrom), m_pszFolderPath);
  608. pCur += ufldrPathLen;
  609. *pCur++ = TEXT('\\');
  610. StringCchCopy(pCur, cchReqd - (pCur -pFrom), pjid->GetPath());
  611. StringCchCat(pCur, cchReqd - (pCur -pFrom), pjid->GetExtension());
  612. pCur += lstrlen(pCur) + 1;
  613. }
  614. // Make sure we have double trailing NULL!
  615. *pCur = TEXT('\0');
  616. SHFILEOPSTRUCT fo;
  617. fo.hwnd = m_hwnd;
  618. fo.wFunc = FO_DELETE;
  619. fo.pFrom = pFrom;
  620. fo.pTo = NULL;
  621. fo.fFlags = FOF_ALLOWUNDO;
  622. fo.fAnyOperationsAborted = FALSE;
  623. fo.hNameMappings = NULL;
  624. fo.lpszProgressTitle = NULL;
  625. HRESULT hr = S_OK;
  626. if ((SHFileOperation(&fo) !=0) || fo.fAnyOperationsAborted == TRUE)
  627. {
  628. hr = E_FAIL;
  629. CHECK_HRESULT(hr);
  630. }
  631. delete pFrom;
  632. return hr;
  633. }
  634. /////////////////////////////////////////////////////////////////////////////
  635. //
  636. // Display properties
  637. //
  638. // from ..\ps\jobpages.cxx
  639. HRESULT
  640. DisplayJobProperties(
  641. LPDATAOBJECT pdtobj);
  642. DWORD
  643. __stdcall
  644. JFPropertiesThread(
  645. LPVOID pvData)
  646. {
  647. LPDATAOBJECT pdtobj = (LPDATAOBJECT)pvData;
  648. HRESULT hrOle = OleInitialize(NULL);
  649. __try
  650. {
  651. if (SUCCEEDED(hrOle))
  652. {
  653. ::DisplayJobProperties(pdtobj);
  654. }
  655. }
  656. __finally
  657. {
  658. pdtobj->Release();
  659. if (SUCCEEDED(hrOle))
  660. {
  661. OleUninitialize();
  662. }
  663. ExitThread(0);
  664. }
  665. return 0;
  666. }
  667. //____________________________________________________________________________
  668. //
  669. // Member: CJobsCM::_DisplayJobProperties
  670. //
  671. // Arguments: [hwnd] -- IN
  672. // [pwszJob] -- IN
  673. //
  674. // Returns: HRESULT.
  675. //
  676. // History: 1/11/1996 RaviR Created
  677. //
  678. //____________________________________________________________________________
  679. HRESULT
  680. CJobsCM::_DisplayJobProperties(
  681. HWND hwnd,
  682. CJobID & jid)
  683. {
  684. TRACE(CJobsCM, _DisplayJobProperties);
  685. Win4Assert(m_cidl == 1);
  686. HRESULT hr = S_OK;
  687. LPDATAOBJECT pdtobj = NULL;
  688. do
  689. {
  690. hr = JFGetDataObject(m_pszFolderPath,
  691. m_pidlFolder,
  692. m_cidl,
  693. (LPCITEMIDLIST *)m_apidl,
  694. FALSE,
  695. (LPVOID *)&pdtobj);
  696. CHECK_HRESULT(hr);
  697. BREAK_ON_FAIL(hr);
  698. HANDLE hThread;
  699. DWORD idThread;
  700. hThread = CreateThread(NULL, 0, JFPropertiesThread,
  701. pdtobj, 0, &idThread);
  702. if (hThread)
  703. {
  704. CloseHandle(hThread);
  705. }
  706. else
  707. {
  708. pdtobj->Release();
  709. }
  710. } while (0);
  711. return hr;
  712. }
  713. //____________________________________________________________________________
  714. //
  715. // Function: JFGetItemContextMenu
  716. //
  717. // Synopsis: S
  718. //
  719. // Arguments: [hwnd] -- IN
  720. // [pScheduler] -- IN
  721. // [cidl] -- IN
  722. // [apidl] -- IN
  723. // [ppvOut] -- OUT
  724. //
  725. // Returns: HRESULT
  726. //
  727. // History: 1/25/1996 RaviR Created
  728. //____________________________________________________________________________
  729. HRESULT
  730. JFGetItemContextMenu(
  731. HWND hwnd,
  732. ITaskScheduler * pScheduler,
  733. LPCTSTR ptszMachine,
  734. LPCTSTR pszFolderPath,
  735. LPCITEMIDLIST pidlFolder,
  736. UINT cidl,
  737. LPCITEMIDLIST* apidl,
  738. LPVOID * ppvOut)
  739. {
  740. CJobsCM* pObj = new CJobsCM(hwnd, pScheduler, ptszMachine);
  741. if (NULL == pObj)
  742. {
  743. return E_OUTOFMEMORY;
  744. }
  745. HRESULT hr = pObj->InitInstance(pszFolderPath, pidlFolder, cidl, apidl);
  746. if (SUCCEEDED(hr))
  747. {
  748. hr = pObj->QueryInterface(IID_IContextMenu, ppvOut);
  749. }
  750. pObj->Release();
  751. return hr;
  752. }