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.

1859 lines
43 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1995.
  5. //
  6. // File: jobfldr.cxx
  7. //
  8. // Contents: Implementation of COM object CJobFolder
  9. //
  10. // Classes: CJobFolder
  11. //
  12. // History: 1/4/1996 RaviR Created
  13. // 1-23-1997 DavidMun Add m_hwndNotify
  14. //
  15. //----------------------------------------------------------------------------
  16. #include "..\pch\headers.hxx"
  17. #pragma hdrstop
  18. #include "dbg.h"
  19. #include "macros.h"
  20. #include "..\inc\resource.h"
  21. #include "resource.h"
  22. #include "sch_cls.hxx" // sched\inc
  23. #include "job_cls.hxx" // sched\inc
  24. #include "misc.hxx" // sched\inc
  25. #include "policy.hxx" // sched\inc
  26. #include "jobidl.hxx"
  27. #include "jobfldr.hxx"
  28. #include "common.hxx"
  29. #include "guids.h"
  30. #include "util.hxx"
  31. #include "avl.hxx"
  32. //#undef DEB_TRACE
  33. //#define DEB_TRACE DEB_USER1
  34. #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
  35. BOOL
  36. UserCanChangeService(
  37. LPCTSTR ptszServer);
  38. HRESULT
  39. PromptForServiceStart(
  40. HWND hwnd);
  41. BOOL
  42. IsMsNetwork( LPTSTR ptszMachine );
  43. //____________________________________________________________________________
  44. //
  45. // Member: CJobFolder::~CJobFolder, Destructor
  46. //____________________________________________________________________________
  47. CJobFolder::~CJobFolder()
  48. {
  49. TRACE(CJobFolder, ~CJobFolder);
  50. if (m_uRegister)
  51. {
  52. DEBUG_OUT((DEB_ERROR,
  53. "CJobFolder::~CJobFolder: m_uRegister = %uL but should be 0\n",
  54. m_uRegister));
  55. SHChangeNotifyDeregister(m_uRegister);
  56. m_uRegister = 0;
  57. CDll::LockServer(FALSE);
  58. }
  59. if (m_hwndNotify)
  60. {
  61. DEBUG_OUT((DEB_ERROR,
  62. "CJobFolder::~CJobFolder: m_hwndNotify = 0x%x but should be NULL\n",
  63. m_hwndNotify));
  64. BOOL fOk = DestroyWindow(m_hwndNotify);
  65. if (!fOk)
  66. {
  67. DEBUG_OUT_LASTERROR;
  68. }
  69. }
  70. delete m_pszMachine;
  71. if (m_pUpdateDirData)
  72. {
  73. GlobalFree(m_pUpdateDirData);
  74. }
  75. if (m_pidlFldr)
  76. {
  77. ILFree(m_pidlFldr);
  78. }
  79. // No need to Release m_pShellView since we never addrefed it.
  80. // See CreateViewObject in sfolder.cxx for more info.
  81. if (m_pScheduler != NULL)
  82. {
  83. DEBUG_OUT((DEB_USER1, "m_pScheduler->Release\n"));
  84. m_pScheduler->Release();
  85. }
  86. OleUninitialize();
  87. }
  88. HRESULT
  89. CJobFolder::_AddObject(
  90. PJOBID pjid,
  91. LPITEMIDLIST *ppidl)
  92. {
  93. HRESULT hr = S_OK;
  94. INT_PTR iRet = -1;
  95. LPITEMIDLIST pidl = ILClone((LPCITEMIDLIST)pjid);
  96. if (pidl == NULL)
  97. {
  98. hr = E_OUTOFMEMORY;
  99. CHECK_HRESULT(hr);
  100. return hr;
  101. }
  102. #if (DBG == 1)
  103. ((PJOBID) pidl)->Validate();
  104. #endif // (DBG == 1)
  105. iRet = ShellFolderView_AddObject(m_hwndOwner, pidl);
  106. if (iRet < 0)
  107. {
  108. ILFree(pidl);
  109. pidl = NULL;
  110. hr = E_FAIL;
  111. CHECK_HRESULT(hr);
  112. }
  113. if (ppidl)
  114. {
  115. *ppidl = pidl;
  116. }
  117. return hr;
  118. }
  119. //+--------------------------------------------------------------------------
  120. //
  121. // Member: CJobFolder::_UpdateObject
  122. //
  123. // Synopsis: Notify the shell defview that the object with pidl [pjidOld]
  124. // has been updated and now should look like pidl [pjidNew].
  125. //
  126. // Arguments: [pjidOld] - pidl of object as it appears in defview
  127. // [pjidNew] - pidl of object as it should now appear
  128. // [ppidl] - filled with pidl of updated object
  129. //
  130. // Returns: HRESULT
  131. //
  132. // Modifies: *[ppidl]
  133. //
  134. // History: 7-07-1999 davidmun Commented
  135. //
  136. // Notes: Do not free returned pidl in *[ppidl].
  137. //
  138. //---------------------------------------------------------------------------
  139. HRESULT
  140. CJobFolder::_UpdateObject(
  141. PJOBID pjidOld,
  142. PJOBID pjidNew,
  143. LPITEMIDLIST *ppidl)
  144. {
  145. TRACE(CJobFolder, _UpdateObject);
  146. HRESULT hr = S_OK;
  147. INT_PTR iRet = -1;
  148. #if (DBG == 1)
  149. DEBUG_OUT((DEB_TRACE,
  150. "CJobFolder::_UpdateObject Validating pjidNew %x\n",
  151. pjidNew));
  152. pjidNew->Validate();
  153. #endif // (DBG == 1)
  154. LPITEMIDLIST pidlCopyOfNew = ILClone((LPCITEMIDLIST)pjidNew);
  155. if (pidlCopyOfNew == NULL)
  156. {
  157. hr = E_OUTOFMEMORY;
  158. CHECK_HRESULT(hr);
  159. return hr;
  160. }
  161. #if (DBG == 1)
  162. DEBUG_OUT((DEB_TRACE,
  163. "CJobFolder::_UpdateObject Validating pidlCopyOfNew %x\n",
  164. pidlCopyOfNew));
  165. ((PJOBID) pidlCopyOfNew)->Validate();
  166. DEBUG_OUT((DEB_TRACE,
  167. "CJobFolder::_UpdateObject Validating pjidOld %x\n",
  168. pjidOld));
  169. pjidOld->Validate();
  170. #endif // (DBG == 1)
  171. LPITEMIDLIST apidl[2] = {(LPITEMIDLIST)pjidOld, pidlCopyOfNew};
  172. iRet = ShellFolderView_UpdateObject(m_hwndOwner, apidl);
  173. if (iRet < 0)
  174. {
  175. //
  176. // The object to update couldn't be found, so the shell won't
  177. // take ownership of the new object, and we have to free it now.
  178. //
  179. ILFree(pidlCopyOfNew);
  180. pidlCopyOfNew = NULL;
  181. }
  182. if (ppidl)
  183. {
  184. *ppidl = (LPITEMIDLIST)ShellFolderView_GetObject(m_hwndOwner, iRet);
  185. #if (DBG == 1)
  186. if (*ppidl)
  187. {
  188. DEBUG_OUT((DEB_TRACE,
  189. "CJobFolder::_UpdateObject Validating *ppidl %x\n",
  190. *ppidl));
  191. ((PJOBID) *ppidl)->Validate();
  192. }
  193. else
  194. {
  195. DEBUG_OUT((DEB_TRACE, "CJobFolder::_UpdateObject *ppidl is NULL\n"));
  196. }
  197. #endif // (DBG == 1)
  198. }
  199. DEBUG_OUT((DEB_TRACE, "<CJobFolder::_UpdateObject\n"));
  200. return hr;
  201. }
  202. //____________________________________________________________________________
  203. //
  204. // Function: JFGetJobFolder
  205. //
  206. // Synopsis: Create an instance of CJobFolder and return the requested
  207. // interface.
  208. //
  209. // Arguments: [riid] -- IN interface needed.
  210. // [ppvObj] -- OUT place to store the interface.
  211. //
  212. // Returns: HRESULT
  213. //
  214. // History: 1/24/1996 RaviR Created
  215. //____________________________________________________________________________
  216. HRESULT
  217. JFGetJobFolder(
  218. REFIID riid,
  219. LPVOID* ppvObj)
  220. {
  221. CJobFolder * pJobFolder = NULL;
  222. HRESULT hr = CJobFolder::Create(&pJobFolder);
  223. if (SUCCEEDED(hr))
  224. {
  225. hr = pJobFolder->QueryInterface(riid, ppvObj);
  226. pJobFolder->Release();
  227. }
  228. return hr;
  229. }
  230. //____________________________________________________________________________
  231. //
  232. // Member: CJobFolder::Create
  233. //
  234. // History: 1/31/1996 RaviR Created
  235. //____________________________________________________________________________
  236. HRESULT
  237. CJobFolder::Create(
  238. CJobFolder ** ppJobFolder)
  239. {
  240. TRACE_FUNCTION(CJobFolder::Create);
  241. HRESULT hr = OleInitialize(NULL);
  242. CHECK_HRESULT(hr);
  243. if (SUCCEEDED(hr))
  244. {
  245. CJobFolder *pJobFolder;
  246. pJobFolder = new CJobFolder();
  247. if (pJobFolder != NULL)
  248. {
  249. *ppJobFolder = pJobFolder;
  250. hr = S_OK;
  251. }
  252. else
  253. {
  254. hr = E_OUTOFMEMORY;
  255. CHECK_HRESULT(hr);
  256. OleUninitialize();
  257. }
  258. }
  259. return hr;
  260. }
  261. //____________________________________________________________________________
  262. //
  263. // Member: CJobFolder::IUnknown methods
  264. //
  265. // History: 1/31/1996 RaviR Created
  266. //____________________________________________________________________________
  267. IMPLEMENT_STANDARD_IUNKNOWN(CJobFolder);
  268. STDMETHODIMP
  269. CJobFolder::QueryInterface(REFIID riid, LPVOID* ppvObj)
  270. {
  271. LPUNKNOWN punk = NULL;
  272. if (IsEqualIID(IID_IUnknown, riid) ||
  273. IsEqualIID(IID_IShellFolder, riid))
  274. {
  275. punk = (IUnknown*) (IShellFolder*) this;
  276. }
  277. else if (IsEqualIID(IID_IPersistFolder, riid))
  278. {
  279. punk = (IUnknown*) (IPersistFolder*) this;
  280. }
  281. #if (_WIN32_IE >= 0x0400)
  282. else if (IsEqualIID(IID_IPersistFolder2, riid))
  283. {
  284. punk = (IUnknown*) (IPersistFolder2*) this;
  285. }
  286. #endif (_WIN32_IE >= 0x0400)
  287. else if (IsEqualIID(IID_IDropTarget, riid))
  288. {
  289. punk = (IUnknown*) (IDropTarget*) this;
  290. }
  291. else if (IsEqualIID(IID_IRemoteComputer, riid))
  292. {
  293. punk = (IUnknown*) (IRemoteComputer*) this;
  294. }
  295. else
  296. {
  297. *ppvObj = NULL;
  298. return E_NOINTERFACE;
  299. }
  300. *ppvObj = punk;
  301. punk->AddRef();
  302. return S_OK;
  303. }
  304. //____________________________________________________________________________
  305. //
  306. // Member: CJobFolder::IRemoteComputer::Initialize
  307. //
  308. // Synopsis: This method is called when the explorer is initializing or
  309. // enumerating the name space extension. If failure is returned
  310. // during enumeration, the extension won't appear for this
  311. // computer. Otherwise, the extension will appear, and should
  312. // target the given machine.
  313. //
  314. // Arguments: [pwszMachine] -- IN Specifies the name of the machine to target.
  315. // [bEnumerating] -- IN
  316. //
  317. // Returns: HRESULT.
  318. //
  319. // History: 2/21/1996 RaviR Created
  320. //
  321. //____________________________________________________________________________
  322. STDMETHODIMP
  323. CJobFolder::Initialize(
  324. LPCWSTR pwszMachine,
  325. BOOL bEnumerating)
  326. {
  327. DEBUG_OUT((DEB_USER12,
  328. "CJobFolder::IRemoteComputer::Initialize<%ws>\n",
  329. pwszMachine));
  330. HRESULT hr = S_OK;
  331. LPTSTR ptszMachine = NULL;
  332. do
  333. {
  334. if (!pwszMachine)
  335. {
  336. hr = E_INVALIDARG;
  337. CHECK_HRESULT(hr);
  338. break;
  339. }
  340. //
  341. // Make a copy of the machine name.
  342. //
  343. #ifdef UNICODE
  344. ptszMachine = NewDupString(pwszMachine);
  345. if (!ptszMachine)
  346. {
  347. hr = E_OUTOFMEMORY;
  348. CHECK_HRESULT(hr);
  349. break;
  350. }
  351. #else
  352. ULONG cbMachine = 1 + 2 * wcslen(pwszMachine);
  353. ptszMachine = new CHAR[cbMachine];
  354. if (!ptszMachine)
  355. {
  356. hr = E_OUTOFMEMORY;
  357. CHECK_HRESULT(hr);
  358. break;
  359. }
  360. hr = UnicodeToAnsi(ptszMachine, pwszMachine, cbMachine);
  361. if (FAILED(hr))
  362. {
  363. CHECK_HRESULT(hr);
  364. break;
  365. }
  366. #endif // UNICODE
  367. //
  368. // The first thing about showing a remote folder is it must be
  369. // a MS network or else the RegConnectregistry time out will
  370. // take at least 20 seconds and there won't even be a MSTask
  371. // on the machine.
  372. if( !IsMsNetwork( ptszMachine ) )
  373. {
  374. return E_FAIL;
  375. }
  376. //
  377. // We only want to show the remote jobs folder if the user has
  378. // administrative access to that machine, and the task scheduler
  379. // is installed there.
  380. //
  381. // Test both at once by trying to get a full access handle to
  382. // the remote machine's task scheduler reg key.
  383. //
  384. if (bEnumerating)
  385. {
  386. //
  387. // Check if the schedule service is registered on pwszMachine.
  388. //
  389. long lr = ERROR_SUCCESS;
  390. HKEY hRemoteKey = NULL;
  391. HKEY hSchedKey = NULL;
  392. lr = RegConnectRegistry(ptszMachine,
  393. HKEY_LOCAL_MACHINE,
  394. &hRemoteKey);
  395. CHECK_LASTERROR(lr);
  396. if (lr == ERROR_SUCCESS)
  397. {
  398. lr = RegOpenKeyEx(hRemoteKey,
  399. SCH_AGENT_KEY,
  400. 0,
  401. KEY_ALL_ACCESS,
  402. &hSchedKey);
  403. CHECK_LASTERROR(lr);
  404. }
  405. if (hRemoteKey != NULL)
  406. {
  407. RegCloseKey(hRemoteKey);
  408. }
  409. if (hSchedKey != NULL)
  410. {
  411. RegCloseKey(hSchedKey);
  412. }
  413. if (lr != ERROR_SUCCESS)
  414. {
  415. hr = HRESULT_FROM_WIN32(lr);
  416. break;
  417. }
  418. }
  419. //
  420. // Success; remember the machine name.
  421. //
  422. m_pszMachine = ptszMachine;
  423. } while (0);
  424. if (FAILED(hr))
  425. {
  426. delete [] ptszMachine;
  427. }
  428. return hr;
  429. }
  430. //____________________________________________________________________________
  431. //
  432. //
  433. // Support function: MsNetwork
  434. //
  435. // Synopsis: Resolves whether or not we're attempting to connect to
  436. // a MS network
  437. //
  438. // History: 11/12/00 DGrube Created
  439. //
  440. //
  441. //____________________________________________________________________________
  442. BOOL IsMsNetwork( LPTSTR ptszMachine )
  443. {
  444. DWORD dwError;
  445. NETRESOURCE nr;
  446. NETRESOURCE nrOut;
  447. LPTSTR pszSystem = NULL; // pointer to variable-length strings
  448. NETRESOURCE* lpBuffer = &nrOut; // buffer
  449. DWORD cbResult = sizeof(nrOut); // buffer size
  450. BOOL bReturn = TRUE;
  451. //
  452. // Fill a block of memory with zeroes; then
  453. // initialize the NETRESOURCE structure.
  454. //
  455. ZeroMemory(&nr, sizeof(nr));
  456. nr.dwScope = RESOURCE_GLOBALNET;
  457. nr.dwType = RESOURCETYPE_ANY;
  458. nr.lpRemoteName = ptszMachine;
  459. //
  460. // First call the WNetGetResourceInformation function with
  461. // memory allocated to hold only a NETRESOURCE structure. This
  462. // method can succeed if all the NETRESOURCE pointers are NULL.
  463. //
  464. dwError = WNetGetResourceInformation(&nr, lpBuffer, &cbResult, &pszSystem);
  465. //
  466. // If the call fails because the buffer is too small,
  467. // call the LocalAlloc function to allocate a larger buffer.
  468. //
  469. if (dwError == ERROR_MORE_DATA)
  470. {
  471. lpBuffer = (NETRESOURCE*) LocalAlloc(LMEM_FIXED, cbResult);
  472. if (lpBuffer == NULL)
  473. {
  474. CHECK_LASTERROR(GetLastError());
  475. return FALSE;
  476. }
  477. }
  478. //
  479. // Call WNetGetResourceInformation again
  480. // with the larger buffer.
  481. //
  482. dwError = WNetGetResourceInformation(&nr, lpBuffer, &cbResult, &pszSystem);
  483. if (dwError == NO_ERROR)
  484. {
  485. // If the call succeeds, process the contents of the
  486. // returned NETRESOURCE structure and the variable-length
  487. // strings in lpBuffer. Then free the memory.
  488. //
  489. if ( NULL != lpBuffer->lpProvider )
  490. {
  491. NETINFOSTRUCT NetInfo;
  492. NetInfo.cbStructure = sizeof( NetInfo );
  493. DWORD dwReturn = WNetGetNetworkInformation( lpBuffer->lpProvider, &NetInfo );
  494. //
  495. // Need to shift 16 bits for masks below because their a DWORD starting at the
  496. // 16th bit and wNetType is a word starting at 0
  497. //
  498. if ( !( ( NetInfo.wNetType == ( WNNC_NET_MSNET >> 16)) ||
  499. ( NetInfo.wNetType == ( WNNC_NET_LANMAN >>16) ) ) )
  500. {
  501. bReturn = FALSE;
  502. }
  503. }
  504. else
  505. {
  506. CHECK_LASTERROR(GetLastError());
  507. bReturn = FALSE;
  508. }
  509. }
  510. else
  511. {
  512. CHECK_LASTERROR(GetLastError());
  513. bReturn = FALSE;
  514. }
  515. if( NULL != lpBuffer )
  516. {
  517. LocalFree( lpBuffer );
  518. }
  519. return bReturn;
  520. }
  521. //____________________________________________________________________________
  522. //
  523. // Member: CJobFolder::IPersistFolder::Initialize
  524. //
  525. // Synopsis: same as IPersistFolder::Initialize
  526. //
  527. // History: 1/31/1996 RaviR Created
  528. //____________________________________________________________________________
  529. STDMETHODIMP
  530. CJobFolder::Initialize(
  531. LPCITEMIDLIST pidl)
  532. {
  533. TRACE(CJobFolder, IPersistFolder::Initialize);
  534. m_pidlFldr = ILClone(pidl);
  535. if (NULL == m_pidlFldr)
  536. {
  537. CHECK_HRESULT(E_OUTOFMEMORY);
  538. return E_OUTOFMEMORY;
  539. }
  540. // NOTE: if this is being invoked remotely, we assume that IRemoteComputer
  541. // is invoked *before* IPersistFolder.
  542. return S_OK;
  543. }
  544. //____________________________________________________________________________
  545. //
  546. // Member: CJobFolder::GetClassID
  547. //
  548. // Synopsis: same as IPersistFolder::GetClassID
  549. //
  550. // History: 1/31/1996 RaviR Created
  551. //____________________________________________________________________________
  552. STDMETHODIMP
  553. CJobFolder::GetClassID(
  554. LPCLSID lpClassID)
  555. {
  556. TRACE(CJobFolder, GetClassID);
  557. *lpClassID = CLSID_CJobFolder;
  558. return S_OK;
  559. }
  560. #if (_WIN32_IE >= 0x0400)
  561. //+--------------------------------------------------------------------------
  562. //
  563. // Member: CJobFolder::IPersistFolder2::GetCurFolder
  564. //
  565. // Synopsis: Return a copy of the item id list for the current folder.
  566. //
  567. // Arguments: [ppidl] - filled with copy of pidl, or NULL on error.
  568. //
  569. // Returns: S_OK or E_OUTOFMEMORY
  570. //
  571. // Modifies: *[ppidl]
  572. //
  573. // History: 12-04-1997 DavidMun Created
  574. //
  575. //---------------------------------------------------------------------------
  576. STDMETHODIMP
  577. CJobFolder::GetCurFolder(
  578. LPITEMIDLIST *ppidl)
  579. {
  580. TRACE(CJobFolder, GetCurFolder);
  581. *ppidl = ILClone(m_pidlFldr);
  582. if (NULL == *ppidl)
  583. {
  584. CHECK_HRESULT(E_OUTOFMEMORY);
  585. return E_OUTOFMEMORY;
  586. }
  587. // NOTE: if this is being invoked remotely, we assume that IRemoteComputer
  588. // is invoked *before* IPersistFolder2.
  589. return S_OK;
  590. }
  591. #endif // (_WIN32_IE >= 0x0400)
  592. //____________________________________________________________________________
  593. //____________________________________________________________________________
  594. //________________ ___________________________________
  595. //________________ Interface IDropTarget ___________________________________
  596. //________________ ___________________________________
  597. //____________________________________________________________________________
  598. //____________________________________________________________________________
  599. //____________________________________________________________________________
  600. //
  601. // Member: CJobFolder::DragEnter
  602. //
  603. // Synopsis: same as IDropTarget::DragEnter
  604. //
  605. // History: 1/31/1996 RaviR Created
  606. //____________________________________________________________________________
  607. HRESULT
  608. CJobFolder::DragEnter(
  609. LPDATAOBJECT pdtobj,
  610. DWORD grfKeyState,
  611. POINTL pt,
  612. DWORD *pdwEffect)
  613. {
  614. DEBUG_OUT((DEB_TRACE, "CJobFolder::DragEnter<%x, dwEffect=%x>\n",
  615. this, *pdwEffect));
  616. m_grfKeyStateLast = grfKeyState;
  617. *pdwEffect = DROPEFFECT_NONE;
  618. //
  619. // Policy - if key TS_KEYPOLICY_DENY_DRAGDROP or DENY_CREATE_TASK
  620. // then we won't allow this
  621. //
  622. if (RegReadPolicyKey(TS_KEYPOLICY_DENY_DRAGDROP) ||
  623. RegReadPolicyKey(TS_KEYPOLICY_DENY_CREATE_TASK))
  624. {
  625. DEBUG_OUT((DEB_ITRACE, "Policy CREATE_TASK or DRAGDROP active - no copy operations\n"));
  626. return S_OK;
  627. }
  628. if (pdtobj != NULL)
  629. {
  630. LPENUMFORMATETC penum;
  631. HRESULT hr;
  632. pdtobj->AddRef();
  633. hr = pdtobj->EnumFormatEtc(DATADIR_GET, &penum);
  634. if (SUCCEEDED(hr))
  635. {
  636. FORMATETC fmte;
  637. ULONG celt;
  638. while (penum->Next(1, &fmte, &celt) == S_OK)
  639. {
  640. if (fmte.cfFormat == CF_HDROP && (fmte.tymed & TYMED_HGLOBAL))
  641. {
  642. // The default action is to MOVE the object. If the user
  643. // has the CONTROL key pressed, then the operation
  644. // becomes a copy
  645. *pdwEffect = DROPEFFECT_MOVE;
  646. if (grfKeyState & MK_CONTROL)
  647. {
  648. *pdwEffect = DROPEFFECT_COPY;
  649. }
  650. break;
  651. }
  652. }
  653. penum->Release();
  654. }
  655. pdtobj->Release();
  656. }
  657. return S_OK;
  658. }
  659. //____________________________________________________________________________
  660. //
  661. // Member: CJobFolder::DragOver
  662. //
  663. // Synopsis: same as IDropTarget::DragOver
  664. //
  665. // History: 1/31/1996 RaviR Created
  666. //____________________________________________________________________________
  667. HRESULT
  668. CJobFolder::DragOver(
  669. DWORD grfKeyState,
  670. POINTL pt,
  671. DWORD *pdwEffect)
  672. {
  673. DEBUG_OUT((DEB_TRACE, "CJobFolder::DragOver<%x, dwEffect=%d>\n",
  674. this, *pdwEffect));
  675. *pdwEffect = DROPEFFECT_NONE;
  676. //
  677. // Policy - if we cannot create a task, or have no drag-drop, deny
  678. // the request
  679. //
  680. if (RegReadPolicyKey(TS_KEYPOLICY_DENY_DRAGDROP) ||
  681. RegReadPolicyKey(TS_KEYPOLICY_DENY_CREATE_TASK))
  682. {
  683. DEBUG_OUT((DEB_ITRACE, "Policy CREATE_TASK or DRAGDROP active - no copy operations\n"));
  684. return S_OK;
  685. }
  686. *pdwEffect = DROPEFFECT_MOVE;
  687. if (grfKeyState & MK_CONTROL)
  688. {
  689. *pdwEffect = DROPEFFECT_COPY;
  690. }
  691. return S_OK;
  692. }
  693. //____________________________________________________________________________
  694. //
  695. // Member: CJobFolder::DragLeave
  696. //
  697. // Synopsis: same as IDropTarget::DragLeave
  698. //
  699. // History: 1/31/1996 RaviR Created
  700. //____________________________________________________________________________
  701. HRESULT
  702. CJobFolder::DragLeave(void)
  703. {
  704. TRACE(CJobFolder, DragLeave);
  705. return S_OK; // Don't need to do anything here...
  706. }
  707. //____________________________________________________________________________
  708. //
  709. // Member: CJobFolder::CopyToFolder
  710. //
  711. // Synopsis: Performs copy of a job obect passed in to this folder
  712. //
  713. // Notes: If policy prevents a copy into this folder, this will
  714. // return E_FAIL. Callers should check this if necessary.
  715. //
  716. // History: 1/31/1996 RaviR Created
  717. // 4/23/1998 CameronE Modified for policy
  718. //____________________________________________________________________________
  719. HRESULT
  720. CJobFolder::CopyToFolder(
  721. LPDATAOBJECT pdtobj,
  722. BOOL fMove,
  723. BOOL fDragDrop, // TRUE if called as a result of a dd op.
  724. POINTL * pPtl) // Valid for a dd op.
  725. {
  726. DEBUG_OUT((DEB_USER12, "CJobFolder::CopyToFolder <<----\n"));
  727. //
  728. // Policy - no copying into the folder if DENY_CREATE_TASK is on
  729. // - no copying via dragdrop, either, if DENY_DRAGDROP is on
  730. //
  731. if (RegReadPolicyKey(TS_KEYPOLICY_DENY_CREATE_TASK) ||
  732. (fDragDrop && RegReadPolicyKey(TS_KEYPOLICY_DENY_DRAGDROP)))
  733. {
  734. DEBUG_OUT((DEB_ITRACE, "Policy CREATE_TASK or DRAGDROP active - no copy operations\n"));
  735. return E_FAIL;
  736. }
  737. BOOL fIsDropOnSrc = ShellFolderView_IsDropOnSource(m_hwndOwner,
  738. (IDropTarget*)this);
  739. STGMEDIUM medium;
  740. FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  741. HRESULT hr = pdtobj->GetData(&fmte, &medium);
  742. if (FAILED(hr))
  743. {
  744. return hr;
  745. }
  746. HDROP hdrop = (HDROP)medium.hGlobal;
  747. UINT cFiles = DragQueryFile(hdrop, (UINT)-1, NULL, 0);
  748. BYTE * rglen = NULL;
  749. LPTSTR pFrom = NULL;
  750. UINT i;
  751. BOOL fCreatedJob = FALSE;
  752. do
  753. {
  754. TCHAR szFileFrom[MAX_PATH+1];
  755. UINT cchFileFrom = ARRAYSIZE(szFileFrom);
  756. BOOL fHasASchedObj = fIsDropOnSrc;
  757. if (fHasASchedObj == FALSE)
  758. {
  759. for (i = 0; i < cFiles; i++)
  760. {
  761. DragQueryFile(hdrop, i, szFileFrom, cchFileFrom);
  762. if (IsAScheduleObject(szFileFrom) == TRUE)
  763. {
  764. fHasASchedObj = TRUE;
  765. break;
  766. }
  767. }
  768. }
  769. if ((fDragDrop == TRUE) &&
  770. (m_grfKeyStateLast & MK_RBUTTON) &&
  771. (fHasASchedObj == TRUE))
  772. {
  773. if (_PopupRBMoveCtx(pPtl->x, pPtl->y, &fMove) == FALSE)
  774. {
  775. hr = S_FALSE;
  776. break;
  777. }
  778. }
  779. if ((fIsDropOnSrc == TRUE) && (fMove == TRUE))
  780. {
  781. // We don't handle positioning in the jobs folder.
  782. hr = S_FALSE;
  783. break;
  784. }
  785. //
  786. // Prepare to copy jobs.
  787. //
  788. if (fHasASchedObj == TRUE)
  789. {
  790. rglen = new BYTE[cFiles];
  791. if (rglen == NULL)
  792. {
  793. hr = E_OUTOFMEMORY;
  794. CHECK_HRESULT(hr);
  795. break;
  796. }
  797. ZeroMemory(rglen, cFiles * sizeof(BYTE));
  798. }
  799. UINT cchReqd = 1; // for an extra null char
  800. for (i = 0; i < cFiles; i++)
  801. {
  802. DragQueryFile(hdrop, i, szFileFrom, cchFileFrom);
  803. if ((fIsDropOnSrc == FALSE) &&
  804. (IsAScheduleObject(szFileFrom) == FALSE))
  805. {
  806. hr = CreateAJobForApp(szFileFrom);
  807. CHECK_HRESULT(hr);
  808. if (SUCCEEDED(hr))
  809. {
  810. fCreatedJob = TRUE;
  811. }
  812. // continue even if an error occurs
  813. continue;
  814. }
  815. if (fHasASchedObj == TRUE)
  816. {
  817. rglen[i] = lstrlen(szFileFrom) + 1;
  818. cchReqd += rglen[i];
  819. }
  820. }
  821. hr = S_OK; // reset CreateAJobForApp might have failed
  822. if (fHasASchedObj == FALSE)
  823. {
  824. break;
  825. }
  826. pFrom = new TCHAR[cchReqd];
  827. if (pFrom == NULL)
  828. {
  829. hr = E_OUTOFMEMORY;
  830. CHECK_HRESULT(hr);
  831. break;
  832. }
  833. LPTSTR pszTemp = pFrom;
  834. for (i = 0; i < cFiles; i++)
  835. {
  836. if (rglen[i])
  837. {
  838. DragQueryFile(hdrop, i, szFileFrom, cchFileFrom);
  839. CopyMemory(pszTemp, szFileFrom, rglen[i] * sizeof(TCHAR));
  840. pszTemp += rglen[i];
  841. }
  842. }
  843. // add extra null char
  844. *pszTemp = TEXT('\0');
  845. SHFILEOPSTRUCT fo = {m_hwndOwner, (fMove ? FO_MOVE : FO_COPY),
  846. pFrom, m_pszFolderPath,
  847. FOF_ALLOWUNDO | (fIsDropOnSrc ? FOF_RENAMEONCOLLISION : 0),
  848. FALSE, NULL, NULL};
  849. if (SHFileOperation(&fo) || fo.fAnyOperationsAborted)
  850. {
  851. hr = E_FAIL;
  852. CHECK_HRESULT(hr);
  853. BREAK_ON_FAIL(hr);
  854. }
  855. fCreatedJob = TRUE;
  856. //
  857. // If the drop was on the job folder shortcut, there is nothing
  858. // else to do here.
  859. //
  860. if (m_hwndOwner == NULL || m_pShellView == NULL)
  861. {
  862. break;
  863. }
  864. //
  865. // If fIsDropOnSource then this was a copy operation from the source
  866. // (if it was a move operation we would've already returned), the
  867. // SHFileOperation has done the rename work for us and will
  868. // create the files.
  869. //
  870. // That will produce a SHCNE_CREATE message for each dropped renamed &
  871. // copied file. CJobFolder::HandleFsNotify will then do an _AddObject
  872. // to put them in the UI.
  873. //
  874. // So in this case we need to leave before adding a bogus copy
  875. // ourselves.
  876. //
  877. if (fIsDropOnSrc == TRUE)
  878. {
  879. break;
  880. }
  881. //
  882. // Add these items to the foldr & select them.
  883. //
  884. LPITEMIDLIST pidl;
  885. CJobID jid;
  886. // First deselect any selected items
  887. LPITEMIDLIST * ppidl;
  888. hr = (HRESULT)ShellFolderView_GetSelectedObjects(m_hwndOwner, &ppidl);
  889. if (SUCCEEDED(hr))
  890. {
  891. i = ShortFromResult(hr);
  892. while (i--)
  893. {
  894. m_pShellView->SelectItem(ppidl[i], SVSI_DESELECT);
  895. }
  896. LocalFree(ppidl);
  897. }
  898. for (i = 0; i < cFiles; i++)
  899. {
  900. if (rglen[i])
  901. {
  902. DragQueryFile(hdrop, i, szFileFrom, cchFileFrom);
  903. LPTSTR pszName = PathFindFileName(szFileFrom);
  904. //
  905. // If a move or copy operation includes objects which collide
  906. // with objects already in the folder, we need to avoid
  907. // creating a bogus duplicate in the UI for those objects.
  908. //
  909. if (_ObjectAlreadyPresent(pszName))
  910. {
  911. continue;
  912. }
  913. hr = jid.Load(m_pszFolderPath, pszName);
  914. BREAK_ON_FAIL(hr);
  915. hr = _AddObject(&jid, &pidl);
  916. BREAK_ON_FAIL(hr);
  917. m_pShellView->SelectItem(pidl, SVSI_SELECT);
  918. }
  919. }
  920. BREAK_ON_FAIL(hr);
  921. } while (0);
  922. if (FAILED(hr))
  923. {
  924. MessageBeep(MB_ICONHAND);
  925. }
  926. else if (fCreatedJob)
  927. {
  928. //
  929. // If the drag/drop operation resulted in a new task being added
  930. // to the tasks folder, prompt the user to start the service
  931. // if it isn't already running.
  932. //
  933. if (UserCanChangeService(m_pszMachine))
  934. {
  935. PromptForServiceStart(m_hwndOwner);
  936. }
  937. }
  938. // clean up
  939. delete pFrom;
  940. delete rglen;
  941. ReleaseStgMedium(&medium);
  942. return S_OK; // Don't need to do anything here...
  943. }
  944. //____________________________________________________________________________
  945. //
  946. // Member: CJobFolder::Drop
  947. //
  948. // Synopsis: same as IDropTarget::Drop
  949. //
  950. // History: 1/31/1996 RaviR Created
  951. //____________________________________________________________________________
  952. HRESULT
  953. CJobFolder::Drop(
  954. LPDATAOBJECT pdtobj,
  955. DWORD grfKeyState,
  956. POINTL ptl,
  957. DWORD *pdwEffect)
  958. {
  959. DEBUG_OUT((DEB_USER1, "CJobFolder::Drop <<----\n"));
  960. *pdwEffect = DROPEFFECT_NONE;
  961. //
  962. // Policy - we should never get here, since we disabled
  963. // it in DragEnter and DragOver, but just in case
  964. //
  965. if (RegReadPolicyKey(TS_KEYPOLICY_DENY_CREATE_TASK) ||
  966. RegReadPolicyKey(TS_KEYPOLICY_DENY_DRAGDROP))
  967. {
  968. return S_OK;
  969. }
  970. BOOL fMove = !(grfKeyState & MK_CONTROL);
  971. DEBUG_OUT((DEB_USER12, "CJobFolder::Drop <%s>\n", fMove ? "Move" : "Copy"));
  972. return CopyToFolder(pdtobj, fMove, TRUE, &ptl);
  973. }
  974. BOOL
  975. CJobFolder::_PopupRBMoveCtx(
  976. LONG x,
  977. LONG y,
  978. BOOL * pfMove)
  979. {
  980. DEBUG_OUT((DEB_USER1, "CJobFolder::_PopupRBMoveCtx\n"));
  981. const TCHAR c_szStatic[] = TEXT("Static");
  982. int iRet = FALSE;
  983. HWND hwndDummy = CreateWindow(c_szStatic, NULL, 0, x, y, 1, 1,
  984. m_hwndOwner, // HWND_DESKTOP,
  985. NULL, g_hInstance, NULL);
  986. if (hwndDummy)
  987. {
  988. HWND hwndPrev = GetForegroundWindow(); // to restore
  989. UINT uFlags = TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_LEFTALIGN;
  990. HMENU popup;
  991. HMENU subpopup;
  992. popup = LoadMenu(g_hInstance, MAKEINTRESOURCE(POPUP_RBUTTON_MOVE));
  993. subpopup = GetSubMenu(popup, 0);
  994. SetForegroundWindow(hwndDummy);
  995. SetFocus(hwndDummy);
  996. iRet = TrackPopupMenu(subpopup, uFlags, x, y, 0, hwndDummy, NULL);
  997. DestroyMenu(popup);
  998. if (iRet)
  999. {
  1000. // non-cancel item is selected. Make the hwndOwner foreground.
  1001. SetForegroundWindow(m_hwndOwner);
  1002. SetFocus(m_hwndOwner);
  1003. }
  1004. else
  1005. {
  1006. //
  1007. // The user canceled the menu. Restore the previous foreground
  1008. // window (before destroying hwndDummy).
  1009. //
  1010. if (hwndPrev)
  1011. {
  1012. SetForegroundWindow(hwndPrev);
  1013. }
  1014. }
  1015. DestroyWindow(hwndDummy);
  1016. }
  1017. switch (iRet)
  1018. {
  1019. case DDIDM_MOVE:
  1020. *pfMove = TRUE;
  1021. return TRUE;
  1022. case DDIDM_COPY:
  1023. *pfMove = FALSE;
  1024. return TRUE;
  1025. case 0:
  1026. default:
  1027. return FALSE;
  1028. }
  1029. }
  1030. //____________________________________________________________________________
  1031. //
  1032. // Member: CJobFolder::CreateAJobForApp
  1033. //
  1034. // Synopsis: Creates a job for the given app.
  1035. // If (pszApp != 0) job name <- app name with ext changed to job
  1036. // Else job name <- "New Job.job", with rename.
  1037. //
  1038. // Arguments: [pszApp] -- IN
  1039. //
  1040. // Returns: HRESULT
  1041. // --- E_FAIL if policy is on preventing creation. Callers
  1042. // should check this if are contingent on a job being made.
  1043. //
  1044. // History: 4/4/1996 RaviR Created
  1045. //
  1046. //____________________________________________________________________________
  1047. HRESULT
  1048. CJobFolder::CreateAJobForApp(
  1049. LPCTSTR pszApp)
  1050. {
  1051. HRESULT hr = S_OK;
  1052. //
  1053. // Policy - if we have the regkey DENY_CREATE_TASK active
  1054. // we cannot permit new jobs to be created via the ui
  1055. //
  1056. if (RegReadPolicyKey(TS_KEYPOLICY_DENY_CREATE_TASK))
  1057. {
  1058. DEBUG_OUT((DEB_ITRACE, "Policy CREATE_TASK active - no drag-drop or copy/cut/paste\n"));
  1059. return E_FAIL;
  1060. }
  1061. CJob * pCJob = CJob::Create();
  1062. if (pCJob == NULL)
  1063. {
  1064. hr = E_OUTOFMEMORY;
  1065. CHECK_HRESULT(hr);
  1066. return hr;
  1067. }
  1068. #ifndef UNICODE
  1069. WCHAR wcBuf[MAX_PATH];
  1070. #endif
  1071. do
  1072. {
  1073. DWORD dwAddFlags = TASK_FLAG_DONT_START_IF_ON_BATTERIES |
  1074. TASK_FLAG_KILL_IF_GOING_ON_BATTERIES;
  1075. hr = pCJob->SetFlags(dwAddFlags);
  1076. CHECK_HRESULT(hr);
  1077. BREAK_ON_FAIL(hr);
  1078. //
  1079. // Create and set a default trigger for ever day at 9:00 AM, with
  1080. // no repetition.
  1081. //
  1082. TASK_TRIGGER jt;
  1083. SYSTEMTIME stNow;
  1084. GetSystemTime(&stNow);
  1085. ZeroMemory(&jt, sizeof(jt));
  1086. jt.cbTriggerSize = sizeof(jt);
  1087. jt.wBeginYear = stNow.wYear;
  1088. jt.wBeginMonth = stNow.wMonth;
  1089. jt.wBeginDay = stNow.wDay;
  1090. jt.TriggerType = TASK_TIME_TRIGGER_DAILY;
  1091. jt.Type.Daily.DaysInterval = 1;
  1092. jt.wStartHour = 9;
  1093. jt.wStartMinute = 0;
  1094. jt.rgFlags = 0;
  1095. ITaskTrigger * pTrigger = NULL;
  1096. WORD iTrigger = (WORD)-1;
  1097. hr = pCJob->CreateTrigger(&iTrigger, &pTrigger);
  1098. CHECK_HRESULT(hr);
  1099. BREAK_ON_FAIL(hr);
  1100. hr = pTrigger->SetTrigger((const PTASK_TRIGGER)&jt);
  1101. pTrigger->Release();
  1102. CHECK_HRESULT(hr);
  1103. BREAK_ON_FAIL(hr);
  1104. TCHAR szJob[MAX_PATH+12];
  1105. lstrcpy(szJob, m_pszFolderPath);
  1106. lstrcat(szJob, TEXT("\\"));
  1107. if (pszApp != NULL)
  1108. {
  1109. // set the app name
  1110. #ifdef UNICODE
  1111. hr = pCJob->SetApplicationName(pszApp);
  1112. #else
  1113. hr = AnsiToUnicode(wcBuf, pszApp, MAX_PATH);
  1114. CHECK_HRESULT(hr);
  1115. BREAK_ON_FAIL(hr);
  1116. hr = pCJob->SetApplicationName(wcBuf);
  1117. #endif
  1118. CHECK_HRESULT(hr);
  1119. BREAK_ON_FAIL(hr);
  1120. // the job name ...
  1121. lstrcat(szJob, PathFindFileName(pszApp));
  1122. LPTSTR pszExt = PathFindExtension(szJob);
  1123. lstrcpy(pszExt, TSZ_DOTJOB);
  1124. }
  1125. else
  1126. {
  1127. UINT len = lstrlen(szJob);
  1128. static int s_nLengthOK = -1;
  1129. if (s_nLengthOK == -1)
  1130. {
  1131. UINT uiTemp = (UINT)LoadString(g_hInstance, IDS_NEW_JOB,
  1132. &szJob[len], (MAX_PATH + 12 - len));
  1133. uiTemp += len;
  1134. if (uiTemp <= MAX_PATH)
  1135. {
  1136. s_nLengthOK = 1;
  1137. }
  1138. else
  1139. {
  1140. s_nLengthOK = 0;
  1141. }
  1142. }
  1143. if (s_nLengthOK == 0)
  1144. {
  1145. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  1146. CHECK_HRESULT(hr);
  1147. break;
  1148. }
  1149. LoadString(g_hInstance, IDS_NEW_JOB,
  1150. &szJob[len], (MAX_PATH - len));
  1151. EnsureUniquenessOfFileName(szJob);
  1152. if (lstrlen(szJob) > MAX_PATH)
  1153. {
  1154. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  1155. CHECK_HRESULT(hr);
  1156. break;
  1157. }
  1158. }
  1159. #ifdef UNICODE
  1160. hr = pCJob->Save(szJob, FALSE);
  1161. #else
  1162. hr = AnsiToUnicode(wcBuf, szJob, MAX_PATH);
  1163. CHECK_HRESULT(hr);
  1164. BREAK_ON_FAIL(hr);
  1165. hr = pCJob->Save(wcBuf, FALSE);
  1166. #endif
  1167. CHECK_HRESULT(hr);
  1168. BREAK_ON_FAIL(hr);
  1169. //
  1170. // If the drop was on the job folder shortcut, there is nothing
  1171. // else to do here.
  1172. //
  1173. if (m_hwndOwner == NULL || m_pShellView == NULL)
  1174. {
  1175. break;
  1176. }
  1177. //
  1178. // Add the job to the job folder
  1179. //
  1180. CJobID jid;
  1181. LPTSTR pszJobName = &szJob[lstrlen(m_pszFolderPath)+1];
  1182. //*(pszJobName - 1) = TEXT('\0');
  1183. hr = jid.Load(m_pszFolderPath, pszJobName);
  1184. BREAK_ON_FAIL(hr);
  1185. hr = _AddObject(&jid);
  1186. BREAK_ON_FAIL(hr);
  1187. //
  1188. // If this is a new task prompt the user for rename
  1189. //
  1190. if (pszApp == NULL)
  1191. {
  1192. //
  1193. // Prompt the user to rename the new job.
  1194. //
  1195. if (m_pShellView != NULL)
  1196. {
  1197. hr = m_pShellView->SelectItem(((LPCITEMIDLIST)&jid), SVSI_EDIT);
  1198. CHECK_HRESULT(hr);
  1199. }
  1200. }
  1201. //BREAK_ON_FAIL(hr);
  1202. } while (0);
  1203. if (pCJob != NULL)
  1204. {
  1205. pCJob->Release();
  1206. }
  1207. return hr;
  1208. }
  1209. int
  1210. CJobFolder::_GetJobIDForTask(
  1211. PJOBID *ppjid,
  1212. int count,
  1213. LPTSTR pszTask)
  1214. {
  1215. LPTSTR pszExt = PathFindExtension(pszTask);
  1216. TCHAR tcSave;
  1217. if (pszExt)
  1218. {
  1219. tcSave = *pszExt;
  1220. *pszExt = TEXT('\0');
  1221. }
  1222. //
  1223. // If the folder is empty, count is 0, so initialize iCmp to -1
  1224. // to force the return statement to indicate there was no match.
  1225. //
  1226. int iCmp = -1;
  1227. for (int i=0; i < count; i++)
  1228. {
  1229. #if (DBG == 1)
  1230. ppjid[i]->Validate();
  1231. #endif // (DBG == 1)
  1232. //
  1233. // Don't compare template (virtual) objects against real files.
  1234. //
  1235. if (ppjid[i]->IsTemplate())
  1236. {
  1237. continue;
  1238. }
  1239. iCmp = lstrcmpi(ppjid[i]->GetName(), pszTask);
  1240. if (iCmp >= 0)
  1241. {
  1242. break;
  1243. }
  1244. }
  1245. if (pszExt)
  1246. {
  1247. *pszExt = tcSave;
  1248. }
  1249. return (iCmp == 0) ? i : -1;
  1250. }
  1251. void hsort(PJOBID *ppjid, UINT cObjs);
  1252. void I_Sort(PJOBID * ppjid, UINT cObjs)
  1253. {
  1254. UINT i;
  1255. #if (DBG == 1)
  1256. for (i=0; i < cObjs; i++)
  1257. {
  1258. ppjid[i]->Validate();
  1259. }
  1260. #endif // (DBG == 1)
  1261. if (cObjs < 10)
  1262. {
  1263. UINT k = 0;
  1264. PJOBID pjid;
  1265. for (i=1; i < cObjs; i++)
  1266. {
  1267. for (k=i;
  1268. k && (lstrcmpi(ppjid[k]->GetName(), ppjid[k-1]->GetName()) < 0);
  1269. --k)
  1270. {
  1271. pjid = ppjid[k];
  1272. ppjid[k] = ppjid[k-1];
  1273. ppjid[k-1] = pjid;
  1274. }
  1275. }
  1276. }
  1277. else
  1278. {
  1279. // Heap sort
  1280. hsort(ppjid, cObjs);
  1281. }
  1282. #if (DBG == 1)
  1283. for (i=0; i < cObjs; i++)
  1284. {
  1285. ppjid[i]->Validate();
  1286. }
  1287. #endif // (DBG == 1)
  1288. }
  1289. //____________________________________________________________________________
  1290. //
  1291. // Member: CJobFolder::OnUpdateDir
  1292. //
  1293. // Synopsis: S
  1294. //
  1295. // Returns: void
  1296. //
  1297. // History: 2/20/1996 RaviR Created
  1298. //
  1299. //____________________________________________________________________________
  1300. void
  1301. CJobFolder::OnUpdateDir(void)
  1302. {
  1303. DEBUG_OUT((DEB_USER1, "CJobFolder::OnUpdateDir <<--\n"));
  1304. HRESULT hr = S_OK;
  1305. //
  1306. // First collect all the itemids from the LPSHELLVIEW
  1307. //
  1308. int cObjs = (int) ShellFolderView_GetObjectCount(m_hwndOwner);
  1309. if (m_cObjsAlloced < cObjs)
  1310. {
  1311. // 40 so that it is DWORD aligned
  1312. m_cObjsAlloced = ((cObjs / 40) + 1) * 40;
  1313. //
  1314. // Allocate an extra byte per jobid to use with pbPresent flag
  1315. // array. (See below.)
  1316. //
  1317. DWORD dwBytes = m_cObjsAlloced * (sizeof(PJOBID) + 1);
  1318. if (m_pUpdateDirData == NULL)
  1319. {
  1320. m_pUpdateDirData = (BYTE *)GlobalAlloc(GPTR, dwBytes);
  1321. }
  1322. else
  1323. {
  1324. BYTE * pbTemp = (BYTE *)GlobalReAlloc(m_pUpdateDirData,
  1325. dwBytes, GHND);
  1326. if (pbTemp)
  1327. {
  1328. m_pUpdateDirData = pbTemp;
  1329. }
  1330. else
  1331. {
  1332. GlobalFree(m_pUpdateDirData);
  1333. m_pUpdateDirData = NULL;
  1334. }
  1335. }
  1336. if (m_pUpdateDirData == NULL)
  1337. {
  1338. hr = E_OUTOFMEMORY;
  1339. CHECK_HRESULT(hr);
  1340. m_cObjsAlloced = 0;
  1341. return;
  1342. }
  1343. }
  1344. PJOBID *ppjid = (PJOBID *)m_pUpdateDirData;
  1345. PBYTE pbPresent = m_pUpdateDirData + m_cObjsAlloced * sizeof(PJOBID);
  1346. ZeroMemory(pbPresent, m_cObjsAlloced * sizeof(BYTE));
  1347. for (int i=0; i < cObjs; i++)
  1348. {
  1349. ppjid[i] = (PJOBID)ShellFolderView_GetObject(m_hwndOwner, i);
  1350. #if (DBG == 1)
  1351. ppjid[i]->Validate();
  1352. #endif
  1353. }
  1354. I_Sort(ppjid, cObjs);
  1355. //
  1356. //
  1357. //
  1358. TCHAR szSearchPath[MAX_PATH] = TEXT("");
  1359. lstrcpy(szSearchPath, m_pszFolderPath);
  1360. lstrcat(szSearchPath, TEXT("\\*") TSZ_DOTJOB);
  1361. WIN32_FIND_DATA fd;
  1362. HANDLE hFind = FindFirstFile(szSearchPath, &fd);
  1363. int index;
  1364. if (hFind != INVALID_HANDLE_VALUE)
  1365. {
  1366. CJobID jid;
  1367. while (1)
  1368. {
  1369. index = _GetJobIDForTask(ppjid, cObjs, fd.cFileName);
  1370. if (index < 0)
  1371. {
  1372. // Add item
  1373. hr = jid.Load(m_pszFolderPath, fd.cFileName);
  1374. if (hr == S_OK)
  1375. {
  1376. hr = _AddObject(&jid);
  1377. }
  1378. }
  1379. else
  1380. {
  1381. if (CompareFileTime(&fd.ftCreationTime,
  1382. &ppjid[index]->_ftCreation) ||
  1383. CompareFileTime(&fd.ftLastWriteTime,
  1384. &ppjid[index]->_ftLastWrite))
  1385. {
  1386. // update job
  1387. DEBUG_OUT((DEB_USER12, "OnUpdateDir::UPDATE_ITEM<%ws>\n",
  1388. fd.cFileName));
  1389. hr = jid.Load(m_pszFolderPath, fd.cFileName);
  1390. if (hr == S_OK)
  1391. {
  1392. LPITEMIDLIST pidl;
  1393. hr = _UpdateObject(&jid, &jid, &pidl);
  1394. if (SUCCEEDED(hr))
  1395. {
  1396. ppjid[index] = (PJOBID)pidl;
  1397. }
  1398. // mark as present
  1399. pbPresent[index] = 1;
  1400. }
  1401. }
  1402. else
  1403. {
  1404. // mark as present
  1405. pbPresent[index] = 1;
  1406. }
  1407. }
  1408. //
  1409. // Let us continue even on failure unless it is a memory error
  1410. //
  1411. if (hr == E_OUTOFMEMORY)
  1412. {
  1413. break;
  1414. }
  1415. //
  1416. // Get the next file.
  1417. //
  1418. if (FindNextFile(hFind, &fd) == FALSE)
  1419. {
  1420. if (GetLastError() != ERROR_NO_MORE_FILES)
  1421. {
  1422. CHECK_LASTERROR(GetLastError());
  1423. }
  1424. break;
  1425. }
  1426. }
  1427. FindClose(hFind);
  1428. //
  1429. // Let us continue even on failure unless it is a memory error
  1430. //
  1431. if (hr != E_OUTOFMEMORY)
  1432. {
  1433. //
  1434. // Now delete any old items that are no longer valid, making
  1435. // sure to ignore the template object.
  1436. //
  1437. for (i=0; i < cObjs; i++)
  1438. {
  1439. if (!pbPresent[i] && !ppjid[i]->IsTemplate())
  1440. {
  1441. // Delete object
  1442. _RemoveObject(ppjid[i]);
  1443. }
  1444. }
  1445. }
  1446. }
  1447. else
  1448. {
  1449. if (GetLastError() != ERROR_FILE_NOT_FOUND)
  1450. {
  1451. CHECK_LASTERROR(GetLastError());
  1452. }
  1453. else if (GetLastError() != ERROR_NO_MORE_FILES)
  1454. {
  1455. // delete everything but template objects
  1456. for (i=0; i < cObjs; i++)
  1457. {
  1458. if (!ppjid[i]->IsTemplate())
  1459. {
  1460. _RemoveObject(ppjid[i]);
  1461. }
  1462. }
  1463. }
  1464. }
  1465. if (hr == E_OUTOFMEMORY)
  1466. {
  1467. // Display error message
  1468. }
  1469. DEBUG_OUT((DEB_USER1, "CJobFolder::OnUpdateDir -->>\n"));
  1470. return;
  1471. }