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.

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