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.

2459 lines
61 KiB

  1. //____________________________________________________________________________
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1996.
  5. //
  6. // File: sfolder.cxx
  7. //
  8. // Contents: Implementation of IShellFolder for Job Folders
  9. //
  10. // Classes: CJobFolder::IShellFolder members
  11. //
  12. // Functions:
  13. //
  14. // History: 1/4/1996 RaviR Created
  15. // 1-23-1997 DavidMun Destroy notify window upon receiving
  16. // DVM_WINDOWDESTROY
  17. //
  18. //____________________________________________________________________________
  19. #include "..\pch\headers.hxx"
  20. #pragma hdrstop
  21. #include "dbg.h"
  22. #include "macros.h"
  23. #include "resource.h"
  24. #include "..\schedui\rc.h"
  25. #include "jobidl.hxx"
  26. #include "jobfldr.hxx"
  27. #include "policy.hxx"
  28. #include "..\schedui\timeutil.hxx"
  29. #include "..\schedui\schedui.hxx"
  30. #include "util.hxx"
  31. #include "..\inc\defines.hxx"
  32. #include "..\inc\misc.hxx"
  33. #include "..\inc\common.hxx"
  34. #include "..\inc\sch_cls.hxx"
  35. #include "atacct.h"
  36. #define JF_FSNOTIFY (WM_USER + 0xA1)
  37. #define STUBM_SETDATA (WM_USER + 0xb1)
  38. #define STUBM_GETDATA (WM_USER + 0xb2)
  39. #define VIEW_ICON_MENU_ID 28713
  40. #define VIEW_SMALLICON_MENU_ID 28714
  41. #define VIEW_LIST_MENU_ID 28715
  42. #define VIEW_DETAILS_MENU_ID 28716
  43. //
  44. // extern
  45. //
  46. extern HINSTANCE g_hInstance;
  47. extern "C" UINT g_cfJobIDList;
  48. extern HANDLE g_hActCtx;
  49. HRESULT
  50. JFGetShellDetails(
  51. HWND hwnd,
  52. LPVOID* ppvObj);
  53. HRESULT
  54. JFGetFolderContextMenu(
  55. HWND hwnd,
  56. CJobFolder * pCJobFolder,
  57. LPVOID * ppvObj);
  58. HRESULT
  59. JFGetDataObject(
  60. LPCTSTR pszFolderPath,
  61. LPCITEMIDLIST pidlFolder,
  62. UINT cidl,
  63. LPCITEMIDLIST * apidl,
  64. BOOL fCut,
  65. LPVOID * ppvObj);
  66. HRESULT
  67. JFGetItemContextMenu(
  68. HWND hwnd,
  69. ITaskScheduler * pScheduler,
  70. LPCTSTR ptszMachine,
  71. LPCTSTR pszFolderPath,
  72. LPCITEMIDLIST pidlFolder,
  73. UINT cidl,
  74. LPCITEMIDLIST* apidl,
  75. LPVOID * ppvOut);
  76. HRESULT
  77. JFGetExtractIcon(
  78. LPVOID * ppvObj,
  79. LPCTSTR pszFolderPath,
  80. LPCITEMIDLIST pidl);
  81. HRESULT
  82. JFGetExtractIconA(
  83. LPVOID * ppvObj,
  84. LPCTSTR pszFolderPath,
  85. LPCITEMIDLIST pidl);
  86. HRESULT
  87. JFGetEnumIDList(
  88. ULONG uFlags,
  89. LPCTSTR pszFolderPath,
  90. IEnumWorkItems * pEnumJobs,
  91. LPVOID * ppvObj);
  92. HRESULT
  93. JFCreateNewQueue(
  94. HWND hwnd);
  95. void
  96. OnViewLog(
  97. LPTSTR lpMachineName,
  98. HWND hwndOwner);
  99. HRESULT
  100. GetSchSvcState(
  101. DWORD &dwCurrState);
  102. HRESULT
  103. StopScheduler(void);
  104. HRESULT
  105. StartScheduler(void);
  106. BOOL
  107. UserCanChangeService(
  108. LPCTSTR ptszServer);
  109. HRESULT
  110. PromptForServiceStart(
  111. HWND hwnd);
  112. HRESULT
  113. PauseScheduler(
  114. BOOL fPause);
  115. VOID
  116. SecurityErrorDialog(
  117. HWND hWndOwner,
  118. HRESULT hr);
  119. VOID
  120. GetDefaultDomainAndUserName(
  121. LPTSTR ptszDomainAndUserName,
  122. ULONG cchBuf);
  123. //
  124. // local funcs
  125. //
  126. HWND
  127. I_CreateNotifyWnd(void);
  128. int
  129. LocaleStrCmp(LPCTSTR ptsz1, LPCTSTR ptsz2);
  130. //____________________________________________________________________________
  131. //
  132. // Member: CJobFolder::ParseDisplayName
  133. //____________________________________________________________________________
  134. STDMETHODIMP
  135. CJobFolder::ParseDisplayName(
  136. HWND hwndOwner,
  137. LPBC pbcReserved,
  138. LPOLESTR lpszDisplayName,
  139. ULONG * pchEaten,
  140. LPITEMIDLIST * ppidl,
  141. ULONG * pdwAttributes)
  142. {
  143. TRACE(CJobFolder, ParseDisplayName);
  144. return E_NOTIMPL;
  145. }
  146. //____________________________________________________________________________
  147. //
  148. // Member: CJobFolder::EnumObjects
  149. //
  150. // Arguments: [hwndOwner] -- IN
  151. // [grfFlags] -- IN
  152. // [ppenumIDList] -- OUT
  153. //
  154. // Returns: HRESULT.
  155. //
  156. // History: 1/5/1996 RaviR Created
  157. //
  158. //____________________________________________________________________________
  159. STDMETHODIMP
  160. CJobFolder::EnumObjects(
  161. HWND hwndOwner,
  162. DWORD grfFlags,
  163. LPENUMIDLIST* ppenumUnknown)
  164. {
  165. DEBUG_OUT((DEB_USER12, "CJobFolder::EnumObjects<%x>\n", this));
  166. *ppenumUnknown = NULL;
  167. //
  168. // We dont support folders.
  169. //
  170. if (!(grfFlags & SHCONTF_NONFOLDERS))
  171. {
  172. return E_FAIL;
  173. }
  174. //
  175. // Get the IDList enumerator
  176. //
  177. HRESULT hr = S_OK;
  178. if (m_pScheduler == NULL)
  179. {
  180. hr = _InitRest();
  181. CHECK_HRESULT(hr);
  182. }
  183. IEnumWorkItems * pEnumJobs = NULL;
  184. if (SUCCEEDED(hr))
  185. {
  186. // m_pScheduler is not actually a COM object
  187. // it was created via new, and is an instance of CSchedule
  188. CSchedule* pScheduler;
  189. pScheduler = (CSchedule*)m_pScheduler;
  190. hr = pScheduler->EnumInternal(&pEnumJobs);
  191. if ((hr == E_ACCESSDENIED) && (NULL != hwndOwner))
  192. {
  193. WCHAR* pMessage;
  194. if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
  195. E_ACCESSDENIED, 0, (LPWSTR)&pMessage, 0, NULL))
  196. {
  197. MessageBox(hwndOwner, pMessage, NULL, MB_OK);
  198. LocalFree(pMessage);
  199. }
  200. }
  201. CHECK_HRESULT(hr);
  202. if (SUCCEEDED(hr))
  203. {
  204. hr = JFGetEnumIDList(grfFlags, m_pszFolderPath,
  205. pEnumJobs, (LPVOID*)ppenumUnknown);
  206. CHECK_HRESULT(hr);
  207. pEnumJobs->Release();
  208. }
  209. }
  210. return hr;
  211. }
  212. //____________________________________________________________________________
  213. //
  214. // Member: CJobFolder::BindToObject
  215. //____________________________________________________________________________
  216. STDMETHODIMP
  217. CJobFolder::BindToObject(
  218. LPCITEMIDLIST pidl,
  219. LPBC pbcReserved,
  220. REFIID riid,
  221. LPVOID* ppvOut)
  222. {
  223. TRACE(CJobFolder, BindToObject);
  224. // Job folder doesn't contain sub-folders
  225. return E_NOTIMPL;
  226. }
  227. //____________________________________________________________________________
  228. //
  229. // Member: CJobFolder::BindToStorage
  230. //
  231. // Note: not used in Win95
  232. //____________________________________________________________________________
  233. STDMETHODIMP
  234. CJobFolder::BindToStorage(
  235. LPCITEMIDLIST pidl,
  236. LPBC pbcReserved,
  237. REFIID riid,
  238. LPVOID* ppvObj)
  239. {
  240. TRACE(CJobFolder, BindToStorage);
  241. *ppvObj = NULL;
  242. return E_NOTIMPL;
  243. }
  244. //____________________________________________________________________________
  245. //
  246. // Member: CJobFolder::CompareIDs
  247. //
  248. // Arguments: [lParam] -- IN
  249. // [pidl1] -- IN
  250. // [pidl2] -- IN
  251. //
  252. // Returns: HRESULT.
  253. //
  254. // History: 1/5/1996 RaviR Created
  255. //
  256. //____________________________________________________________________________
  257. STDMETHODIMP
  258. CJobFolder::CompareIDs(
  259. LPARAM lCol,
  260. LPCITEMIDLIST pidl1,
  261. LPCITEMIDLIST pidl2)
  262. {
  263. DEBUG_OUT((DEB_USER12, "CJobFolder::CompareIDs<%d>\n", lCol));
  264. HRESULT hr = S_OK;
  265. int iCmp;
  266. if (JF_IsValidID(pidl1) == FALSE || JF_IsValidID(pidl2) == FALSE)
  267. {
  268. return E_INVALIDARG;
  269. }
  270. PJOBID pjid1 = (PJOBID)pidl1;
  271. PJOBID pjid2 = (PJOBID)pidl2;
  272. //
  273. // Ensure that the template object is always first
  274. //
  275. if (pjid1->IsTemplate() && pjid2->IsTemplate())
  276. {
  277. return S_OK; // equal
  278. }
  279. if (pjid1->IsTemplate())
  280. {
  281. return ResultFromShort(-1);
  282. }
  283. if (pjid2->IsTemplate())
  284. {
  285. return ResultFromShort(1);
  286. }
  287. switch (lCol)
  288. {
  289. case COLUMN_LASTRUNTIME:
  290. iCmp = CompareSystemTime(pjid1->GetLastRunTime(),
  291. pjid2->GetLastRunTime());
  292. break;
  293. case COLUMN_NEXTRUNTIME:
  294. {
  295. TCHAR buff1[MAX_PATH];
  296. TCHAR buff2[MAX_PATH];
  297. LPTSTR psz1, psz2;
  298. psz1 = pjid1->GetNextRunTimeString(buff1, MAX_PATH, TRUE);
  299. psz2 = pjid2->GetNextRunTimeString(buff2, MAX_PATH, TRUE);
  300. if (psz1 != NULL)
  301. {
  302. if (psz2 != NULL)
  303. {
  304. iCmp = LocaleStrCmp(psz1, psz2);
  305. }
  306. else
  307. {
  308. iCmp = 1;
  309. }
  310. }
  311. else
  312. {
  313. if (psz2 != NULL)
  314. {
  315. iCmp = -1;
  316. }
  317. else
  318. {
  319. iCmp = CompareSystemTime(pjid1->GetNextRunTime(),
  320. pjid2->GetNextRunTime());
  321. }
  322. }
  323. break;
  324. }
  325. case COLUMN_SCHEDULE:
  326. {
  327. TCHAR tszTrig1[SCH_XBIGBUF_LEN];
  328. TCHAR tszTrig2[SCH_XBIGBUF_LEN];
  329. if (pjid1->IsJobFlagOn(TASK_FLAG_DISABLED) == TRUE)
  330. {
  331. LoadString(g_hInstance, IDS_DISABLED, tszTrig1, SCH_XBIGBUF_LEN);
  332. }
  333. else
  334. {
  335. hr = GetTriggerStringFromTrigger(&pjid1->GetTrigger(),
  336. tszTrig1, SCH_XBIGBUF_LEN, NULL);
  337. BREAK_ON_FAIL(hr);
  338. }
  339. if (pjid2->IsJobFlagOn(TASK_FLAG_DISABLED) == TRUE)
  340. {
  341. LoadString(g_hInstance, IDS_DISABLED, tszTrig2, SCH_XBIGBUF_LEN);
  342. }
  343. else
  344. {
  345. hr = GetTriggerStringFromTrigger(&pjid2->GetTrigger(),
  346. tszTrig2, SCH_XBIGBUF_LEN, NULL);
  347. BREAK_ON_FAIL(hr);
  348. }
  349. iCmp = LocaleStrCmp(tszTrig1, tszTrig2);
  350. break;
  351. }
  352. case COLUMN_STATUS:
  353. {
  354. iCmp = pjid1->_status - pjid2->_status;
  355. break;
  356. }
  357. case COLUMN_NAME:
  358. // Fall through
  359. default:
  360. DEBUG_OUT((DEB_USER12, "CompareIDs<%ws, %ws>\n", pjid1->GetName(),
  361. pjid2->GetName()));
  362. iCmp = LocaleStrCmp(pjid1->GetName(), pjid2->GetName());
  363. break;
  364. case COLUMN_LASTEXITCODE:
  365. iCmp = pjid1->GetExitCode() - pjid2->GetExitCode();
  366. break;
  367. case COLUMN_CREATOR:
  368. iCmp = LocaleStrCmp(pjid1->GetCreator(), pjid2->GetCreator());
  369. break;
  370. }
  371. if (SUCCEEDED(hr))
  372. {
  373. hr = ResultFromShort(iCmp);
  374. }
  375. return hr;
  376. }
  377. //+---------------------------------------------------------------------------
  378. //
  379. // Function: LocaleStrCmp
  380. //
  381. // Synopsis: Do a case insensitive string compare that is safe for any
  382. // locale.
  383. //
  384. // Arguments: [ptsz1] - strings to compare
  385. // [ptsz2]
  386. //
  387. // Returns: -1, 0, or 1 just like lstrcmpi
  388. //
  389. // History: 10-28-96 DavidMun Created
  390. //
  391. // Notes: This is slower than lstrcmpi, but will work when sorting
  392. // strings even in Japanese.
  393. //
  394. //----------------------------------------------------------------------------
  395. int
  396. LocaleStrCmp(LPCTSTR ptsz1, LPCTSTR ptsz2)
  397. {
  398. int iRet;
  399. iRet = CompareString(LOCALE_USER_DEFAULT,
  400. NORM_IGNORECASE |
  401. NORM_IGNOREKANATYPE |
  402. NORM_IGNOREWIDTH,
  403. ptsz1,
  404. -1,
  405. ptsz2,
  406. -1);
  407. if (iRet)
  408. {
  409. iRet -= 2; // convert to lstrcmpi-style return -1, 0, or 1
  410. }
  411. else
  412. {
  413. DEBUG_OUT_LASTERROR;
  414. }
  415. return iRet;
  416. }
  417. //____________________________________________________________________________
  418. //
  419. // Member: CJobFolder::CreateViewObject
  420. //
  421. // Arguments: [hwndOwner] -- IN
  422. // [riid] -- IN
  423. // [ppvOut] -- IN
  424. //
  425. // Returns: HRESULT.
  426. //
  427. // History: 1/5/1996 RaviR Created
  428. //
  429. //____________________________________________________________________________
  430. STDMETHODIMP
  431. CJobFolder::CreateViewObject(
  432. HWND hwndOwner,
  433. REFIID riid,
  434. LPVOID* ppvOut)
  435. {
  436. TRACE(CJobFolder, CreateViewObject);
  437. HRESULT hr = S_OK;
  438. //
  439. // Only update m_hwndOwner the first time.
  440. // This function gets called each time the view mode gets changed,
  441. // but subsequent calls after initial window creation seem to have bogus
  442. // values for hwndOwner. We don't want to clobber our initial good value.
  443. //
  444. if (!m_hwndOwner)
  445. m_hwndOwner = hwndOwner;
  446. *ppvOut = NULL;
  447. if (m_pszFolderPath == NULL)
  448. {
  449. hr = _InitRest();
  450. CHECK_HRESULT(hr);
  451. if (FAILED(hr))
  452. {
  453. return hr;
  454. }
  455. }
  456. if (IsEqualIID(riid, IID_IShellView))
  457. {
  458. CSFV csfv =
  459. {
  460. sizeof(CSFV), // cbSize
  461. (IShellFolder*)this, // pshf
  462. NULL, // psvOuter
  463. m_pidlFldr, // pidl to monitor
  464. 0, // events
  465. s_JobsFVCallBack, // pfnCallback
  466. FVM_DETAILS
  467. };
  468. IShellView * pShellView;
  469. if (SUCCEEDED(hr))
  470. {
  471. hr = SHCreateShellFolderViewEx(&csfv, &pShellView);
  472. CHECK_HRESULT(hr);
  473. }
  474. if (SUCCEEDED(hr))
  475. {
  476. m_pShellView = pShellView;
  477. // WARNING: Do not AddRef m_pShellView this will cause
  478. // a cyclic addref. Use DVM_RELEASE in callback to know
  479. // whem m_pShellView is destroyed.
  480. }
  481. *ppvOut = (LPVOID)m_pShellView;
  482. }
  483. else if (IsEqualIID(riid, IID_IShellDetails))
  484. {
  485. hr = JFGetShellDetails(hwndOwner, ppvOut);
  486. }
  487. else if (IsEqualIID(riid, IID_IContextMenu))
  488. {
  489. hr = JFGetFolderContextMenu(hwndOwner, this, ppvOut);
  490. }
  491. else if (IsEqualIID(riid, IID_IDropTarget))
  492. {
  493. hr = this->QueryInterface(IID_IDropTarget, ppvOut);
  494. }
  495. else
  496. {
  497. hr = E_NOINTERFACE;
  498. CHECK_HRESULT(hr);
  499. }
  500. return hr;
  501. }
  502. //____________________________________________________________________________
  503. //
  504. // Member: CJobFolder::GetAttributesOf
  505. //
  506. // Arguments: [cidl] -- IN
  507. // [apidl] -- IN
  508. // [rgfInOut] -- IN
  509. //
  510. // Returns: HRESULT.
  511. //
  512. // History: 1/5/1996 RaviR Created
  513. // 5-09-1997 DavidMun handle template object
  514. //
  515. //____________________________________________________________________________
  516. STDMETHODIMP
  517. CJobFolder::GetAttributesOf(
  518. UINT cidl,
  519. LPCITEMIDLIST* apidl,
  520. ULONG* rgfInOut)
  521. {
  522. // TRACE(CJobFolder, GetAttributesOf);
  523. //
  524. // Three cases:
  525. //
  526. // a. list contains only non-template object(s)
  527. // b. list contains only a template object
  528. // c. list contains template object plus non-template object(s)
  529. //
  530. // For cases b and c, no operations are allowed, since the
  531. // template object is not a real object.
  532. //
  533. ULONG rgfMask;
  534. if (ContainsTemplateObject(cidl, apidl))
  535. {
  536. rgfMask = 0;
  537. }
  538. else
  539. {
  540. //
  541. // Policy - creation, deletion are regulated
  542. //
  543. rgfMask = 0;
  544. //
  545. // If no DRAG and DROP restriction, then it ok to copy.
  546. // read it once, for efficiency's sake.
  547. //
  548. BOOL fDragDropRestricted = RegReadPolicyKey(TS_KEYPOLICY_DENY_DRAGDROP);
  549. BOOL fDeleteRestricted = RegReadPolicyKey(TS_KEYPOLICY_DENY_DELETE);
  550. if (! fDragDropRestricted)
  551. {
  552. rgfMask |= SFGAO_CANCOPY;
  553. }
  554. if ((! fDeleteRestricted) && (! fDragDropRestricted))
  555. {
  556. // If allowed deletion, then move or delete is okay
  557. rgfMask |= SFGAO_CANMOVE;
  558. if (! RegReadPolicyKey(TS_KEYPOLICY_DENY_CREATE_TASK))
  559. {
  560. //
  561. // If allowed creation, as well, then rename is okay
  562. // Note we consider a RENAME both a create and a delete
  563. //
  564. rgfMask |= SFGAO_CANRENAME;
  565. }
  566. }
  567. if (! fDeleteRestricted)
  568. {
  569. rgfMask |= SFGAO_CANDELETE;
  570. }
  571. if ((cidl == 1) && (! RegReadPolicyKey(TS_KEYPOLICY_DENY_PROPERTIES)))
  572. {
  573. // no multi-select property sheets
  574. rgfMask |= SFGAO_HASPROPSHEET|SFGAO_FILESYSTEM ;
  575. }
  576. }
  577. *rgfInOut &= rgfMask;
  578. return S_OK;
  579. }
  580. //____________________________________________________________________________
  581. //
  582. // Member: CJobFolder::GetUIObjectOf
  583. //
  584. // Arguments: [hwndOwner] -- IN
  585. // [cidl] -- IN
  586. // [apidl] -- IN
  587. // [riid] -- IN
  588. // [prgfInOut] -- IN
  589. // [ppvOut] -- IN
  590. //
  591. // Returns: STDMETHODIMP
  592. //
  593. // History: 1/5/1996 RaviR Created
  594. //
  595. //____________________________________________________________________________
  596. STDMETHODIMP
  597. CJobFolder::GetUIObjectOf(
  598. HWND hwndOwner,
  599. UINT cidl,
  600. LPCITEMIDLIST* apidl,
  601. REFIID riid,
  602. UINT* prgfInOut,
  603. LPVOID* ppvOut)
  604. {
  605. TRACE(CJobFolder, GetUIObjectOf);
  606. if( NULL == apidl )
  607. {
  608. return E_INVALIDARG;
  609. }
  610. PJOBID pjid = (PJOBID)apidl[0];
  611. if (cidl < 1)
  612. {
  613. return E_INVALIDARG;
  614. }
  615. if (JF_IsValidID(apidl[0]) == FALSE)
  616. {
  617. return E_INVALIDARG;
  618. }
  619. HRESULT hr = E_NOINTERFACE;
  620. *ppvOut = NULL;
  621. if (cidl == 1 && IsEqualIID(riid, IID_IExtractIcon))
  622. {
  623. hr = JFGetExtractIcon(ppvOut, m_pszFolderPath, apidl[0]);
  624. }
  625. else if (cidl == 1 && IsEqualIID(riid, IID_IExtractIconA))
  626. {
  627. hr = JFGetExtractIconA(ppvOut, m_pszFolderPath, apidl[0]);
  628. }
  629. else if (IsEqualIID(riid, IID_IContextMenu))
  630. {
  631. if (m_pszFolderPath == NULL)
  632. {
  633. hr = _InitRest();
  634. CHECK_HRESULT(hr);
  635. if (FAILED(hr))
  636. {
  637. return hr;
  638. }
  639. }
  640. hr = JFGetItemContextMenu(hwndOwner,
  641. m_pScheduler,
  642. m_pszMachine,
  643. m_pszFolderPath,
  644. m_pidlFldr,
  645. cidl,
  646. apidl,
  647. ppvOut);
  648. }
  649. else if (cidl > 0 && IsEqualIID(riid, IID_IDataObject))
  650. {
  651. DEBUG_OUT((DEB_USER1, "[GetUIObjectOf] IDataObject \n"));
  652. BOOL fCut = (GetKeyState(VK_CONTROL) >= 0);
  653. //
  654. // Policy - if DRAGDROP or DELETE and we are here,
  655. // we must be doing a cut or copy op and cannot allow it
  656. //
  657. if (RegReadPolicyKey(TS_KEYPOLICY_DENY_DRAGDROP) ||
  658. (fCut && RegReadPolicyKey(TS_KEYPOLICY_DENY_DELETE)))
  659. {
  660. return E_NOINTERFACE;
  661. }
  662. DEBUG_OUT((DEB_USER12, "fCut<%d>\n", fCut));
  663. hr = JFGetDataObject(m_pszFolderPath,
  664. m_pidlFldr,
  665. cidl,
  666. apidl,
  667. fCut,
  668. ppvOut);
  669. }
  670. return hr;
  671. }
  672. //____________________________________________________________________________
  673. //
  674. // Member: CJobFolder::GetDisplayNameOf
  675. //
  676. // Arguments: [pidl] -- IN
  677. // [uFlags] -- IN
  678. // [lpName] -- IN
  679. //
  680. // Returns: HRESULT.
  681. //
  682. // History: 1/5/1996 RaviR Created
  683. //
  684. //____________________________________________________________________________
  685. STDMETHODIMP
  686. CJobFolder::GetDisplayNameOf(
  687. LPCITEMIDLIST pidl,
  688. DWORD uFlags,
  689. LPSTRRET lpName)
  690. {
  691. TRACE(CJobFolder, GetDisplayNameOf);
  692. DEBUG_OUT((DEB_USER12, "CJobFolder::GetDisplayNameOf<uFlags = %d>\n", uFlags));
  693. if (JF_IsValidID(pidl) == FALSE)
  694. {
  695. return E_INVALIDARG;
  696. }
  697. PJOBID pjid_unaligned = (PJOBID)pidl;
  698. DWORD SizeForAlignment = pjid_unaligned->_cb + sizeof(ULONG_PTR);
  699. CJobID * pjid = (CJobID *)LocalAlloc(LPTR,SizeForAlignment);
  700. if (NULL == pjid)
  701. {
  702. return E_OUTOFMEMORY;
  703. };
  704. class CFreeMe { void * _p; public: CFreeMe(void * p):_p(p){}; ~CFreeMe(){ LocalFree(_p);};} FreeMe(pjid);
  705. memcpy(pjid, pjid_unaligned, pjid_unaligned->_cb);
  706. LPTSTR ptszToReturn;
  707. TCHAR tszFullPath[MAX_PATH + 1];
  708. //
  709. // If the display name is to be used for parsing, return the full path to
  710. // the file. This is used by rshx32.dll when we request that it add the
  711. // security page for a file.
  712. //
  713. if (uFlags & SHGDN_FORPARSING)
  714. {
  715. //
  716. // If we don't have the folder path, complete the initialization to
  717. // get it.
  718. //
  719. if (m_pszFolderPath == NULL)
  720. {
  721. HRESULT hr = _InitRest();
  722. CHECK_HRESULT(hr);
  723. if (FAILED(hr))
  724. {
  725. return hr;
  726. }
  727. }
  728. StringCchPrintf(tszFullPath,
  729. MAX_PATH + 1,
  730. TEXT("%s\\%s.") TSZ_JOB,
  731. m_pszFolderPath,
  732. pjid->GetName());
  733. ptszToReturn = tszFullPath;
  734. DEBUG_OUT((DEB_TRACE,
  735. "CJobFolder::GetDisplayNameOf: Returning path '%S'\n",
  736. ptszToReturn));
  737. }
  738. else
  739. {
  740. ptszToReturn = pjid->GetName();
  741. }
  742. UINT uiByteLen = (lstrlen(ptszToReturn) + 1) * sizeof(TCHAR);
  743. lpName->uType = STRRET_WSTR;
  744. lpName->pOleStr = (LPWSTR) SHAlloc(uiByteLen);
  745. if (NULL == lpName->pOleStr)
  746. {
  747. return E_OUTOFMEMORY;
  748. }
  749. CopyMemory(lpName->pOleStr, ptszToReturn, uiByteLen);
  750. return NOERROR;
  751. }
  752. //____________________________________________________________________________
  753. //
  754. // Member: CJobFolder::SetNameOf
  755. //
  756. // Arguments: [hwndOwner] -- IN
  757. // [pidl] -- IN
  758. // [lpszName] -- IN
  759. // [uFlags] -- IN
  760. // [ppidlOut] -- IN
  761. //
  762. // Returns: STDMETHODIMP
  763. //
  764. // History: 1/5/1996 RaviR Created
  765. //
  766. //____________________________________________________________________________
  767. STDMETHODIMP
  768. CJobFolder::SetNameOf(
  769. HWND hwndOwner,
  770. LPCITEMIDLIST pidl,
  771. LPCOLESTR lpszName,
  772. DWORD uFlags,
  773. LPITEMIDLIST* ppidlOut)
  774. {
  775. TRACE(CJobFolder, SetNameOf);
  776. HRESULT hr = S_OK;
  777. if (JF_IsValidID(pidl) == FALSE)
  778. {
  779. return E_INVALIDARG;
  780. }
  781. PJOBID pjidOld = (PJOBID)pidl;
  782. DEBUG_ASSERT(!pjidOld->IsTemplate());
  783. if (ppidlOut != NULL)
  784. {
  785. *ppidlOut = NULL;
  786. }
  787. CJobID jidNew;
  788. jidNew.Rename(*pjidOld, lpszName);
  789. //
  790. // Change the file name
  791. //
  792. TCHAR szOldFile[MAX_PATH + 2];
  793. TCHAR szNewFile[MAX_PATH + 2];
  794. BOOL fRet;
  795. StringCchCopy(szOldFile, MAX_PATH + 2, m_pszFolderPath);
  796. StringCchCat(szOldFile, MAX_PATH + 2, TEXT("\\"));
  797. StringCchCat(szOldFile, MAX_PATH + 2, pjidOld->GetPath());
  798. StringCchCat(szOldFile, MAX_PATH + 2, TSZ_DOTJOB);
  799. StringCchCopy(szNewFile, MAX_PATH + 2, m_pszFolderPath);
  800. StringCchCat(szNewFile, MAX_PATH + 2, TEXT("\\"));
  801. StringCchCat(szNewFile, MAX_PATH + 2, jidNew.GetName());
  802. StringCchCat(szNewFile, MAX_PATH + 2, TSZ_DOTJOB);
  803. DEBUG_OUT((DEB_USER1, "Rename %ws to %ws\n", szOldFile, szNewFile));
  804. SHFILEOPSTRUCT fo;
  805. fo.hwnd = m_hwndOwner;
  806. fo.wFunc = FO_RENAME;
  807. fo.pFrom = szOldFile;
  808. fo.pTo = szNewFile;
  809. fo.fFlags = FOF_ALLOWUNDO;
  810. fo.fAnyOperationsAborted = FALSE;
  811. fo.hNameMappings = NULL;
  812. fo.lpszProgressTitle = NULL;
  813. // Make sure we have double trailing NULL!
  814. *(szOldFile + lstrlen(szOldFile) + 1) = TEXT('\0');
  815. *(szNewFile + lstrlen(szNewFile) + 1) = TEXT('\0');
  816. if ((SHFileOperation(&fo) !=0) || fo.fAnyOperationsAborted == TRUE)
  817. {
  818. hr = E_FAIL;
  819. CHECK_HRESULT(hr);
  820. return hr;
  821. }
  822. return hr;
  823. }
  824. // IShellFolder2
  825. STDMETHODIMP
  826. CJobFolder::GetDefaultSearchGUID(GUID *pguid)
  827. {
  828. return E_NOTIMPL;
  829. };
  830. STDMETHODIMP
  831. CJobFolder::EnumSearches(IEnumExtraSearch **ppenum)
  832. {
  833. return E_NOTIMPL;
  834. };
  835. STDMETHODIMP
  836. CJobFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
  837. {
  838. if (NULL == pSort || NULL == pDisplay)
  839. {
  840. return E_POINTER;
  841. }
  842. *pSort = COLUMN_NEXTRUNTIME;
  843. *pDisplay = COLUMN_NAME;
  844. return S_OK;
  845. };
  846. STDMETHODIMP
  847. CJobFolder::GetDefaultColumnState( UINT iColumn, SHCOLSTATEF *pcsFlags)
  848. {
  849. if (NULL == pcsFlags)
  850. {
  851. return E_POINTER;
  852. }
  853. if (iColumn >= COLUMN_COUNT)
  854. {
  855. return E_FAIL;
  856. }
  857. switch(iColumn)
  858. {
  859. case COLUMN_NAME:
  860. case COLUMN_SCHEDULE:
  861. *pcsFlags = SHCOLSTATE_ONBYDEFAULT |SHCOLSTATE_TYPE_STR;
  862. break;
  863. case COLUMN_NEXTRUNTIME:
  864. case COLUMN_LASTRUNTIME:
  865. *pcsFlags = SHCOLSTATE_ONBYDEFAULT |SHCOLSTATE_TYPE_DATE;
  866. break;
  867. case COLUMN_STATUS:
  868. case COLUMN_COUNT:
  869. *pcsFlags = SHCOLSTATE_ONBYDEFAULT |SHCOLSTATE_TYPE_INT;
  870. break;
  871. default:
  872. *pcsFlags = SHCOLSTATE_ONBYDEFAULT;
  873. };
  874. return S_OK;
  875. };
  876. STDMETHODIMP
  877. CJobFolder::GetDetailsEx( LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv)
  878. {
  879. return E_NOTIMPL;
  880. };
  881. STDMETHODIMP
  882. CJobFolder::GetDetailsOf( LPCITEMIDLIST pidl,UINT iColumn,SHELLDETAILS *psd)
  883. {
  884. return E_NOTIMPL;
  885. };
  886. STDMETHODIMP
  887. CJobFolder::MapColumnToSCID(UINT iColumn, SHCOLUMNID *pscid)
  888. {
  889. return E_NOTIMPL;
  890. };
  891. #if DBG==1
  892. void JFDbgOutCallbackMsg(UINT uMsg);
  893. #endif // DBG==1
  894. //____________________________________________________________________________
  895. //
  896. // Member: CJobFolder::s_JobsFVCallBack, static
  897. //
  898. // Arguments: [psvOuter] -- IN
  899. // [psf] -- IN
  900. // [hwndOwner] -- IN
  901. // [uMsg] -- IN
  902. // [wParam] -- IN
  903. // [lParam] -- IN
  904. //
  905. // Returns: HRESULT
  906. //
  907. // History: 1/5/1996 RaviR Created
  908. //
  909. //____________________________________________________________________________
  910. HRESULT CALLBACK
  911. CJobFolder::s_JobsFVCallBack(
  912. LPSHELLVIEW psvOuter,
  913. LPSHELLFOLDER psf,
  914. HWND hwndOwner,
  915. UINT uMsg,
  916. WPARAM wParam,
  917. LPARAM lParam)
  918. {
  919. CJobFolder *pCJobFolder = (CJobFolder *)psf;
  920. return pCJobFolder->_JobsFVCallBack(psvOuter, psf, hwndOwner,
  921. uMsg, wParam, lParam);
  922. }
  923. //+---------------------------------------------------------------------------
  924. //
  925. // Function: EnableAtAccountControls
  926. //
  927. // Synopsis: Enable or disable the account and password controls in the
  928. // at account dialog.
  929. //
  930. // Arguments: [hDlg] - handle to dialog
  931. // [fEnable] - TRUE = enable, FALSE = disable
  932. //
  933. // History: 09-19-96 DavidMun Created
  934. //
  935. //----------------------------------------------------------------------------
  936. VOID
  937. EnableAtAccountControls(HWND hDlg, BOOL fEnable)
  938. {
  939. EnableWindow(GetDlgItem(hDlg, IDD_AT_CUSTOM_ACCT_NAME), fEnable);
  940. EnableWindow(GetDlgItem(hDlg, IDD_AT_PASSWORD), fEnable);
  941. EnableWindow(GetDlgItem(hDlg, IDD_AT_CONFIRM_PASSWORD), fEnable);
  942. }
  943. //+---------------------------------------------------------------------------
  944. //
  945. // Function: InitAtAccountDlg
  946. //
  947. // Synopsis: Initialize the controls in the at account dialog
  948. //
  949. // Arguments: [hDlg] - handle to dialog
  950. //
  951. // History: 09-19-96 DavidMun Created
  952. //
  953. //----------------------------------------------------------------------------
  954. VOID
  955. InitAtAccountDlg(HWND hDlg)
  956. {
  957. HRESULT hr;
  958. WCHAR wszAccount[MAX_USERNAME + 1];
  959. DWORD cchAccount = MAX_USERNAME + 1;
  960. //
  961. // Limit the length of account and password edit controls, and init the
  962. // password controls to stars just like the task account dialog does.
  963. //
  964. SendDlgItemMessage(hDlg,
  965. IDD_AT_CUSTOM_ACCT_NAME,
  966. EM_LIMITTEXT,
  967. MAX_USERNAME,
  968. 0);
  969. SendDlgItemMessage(hDlg,
  970. IDD_AT_PASSWORD,
  971. EM_LIMITTEXT,
  972. MAX_PASSWORD,
  973. 0);
  974. SendDlgItemMessage(hDlg,
  975. IDD_AT_CONFIRM_PASSWORD,
  976. EM_LIMITTEXT,
  977. MAX_PASSWORD,
  978. 0);
  979. //
  980. // Ask the service for the current at account information. Menu item for
  981. // this dialog should be disabled if service isn't running, so this should
  982. // succeed. If this fails, we can't expect the Set api to work, so
  983. // complain and bail.
  984. //
  985. hr = GetNetScheduleAccountInformation(NULL, cchAccount, wszAccount);
  986. if (SUCCEEDED(hr))
  987. {
  988. if (hr == S_FALSE)
  989. {
  990. // running as local system
  991. CheckDlgButton(hDlg, IDD_AT_USE_SYSTEM, BST_CHECKED);
  992. EnableAtAccountControls(hDlg, FALSE);
  993. }
  994. else
  995. {
  996. CheckDlgButton(hDlg, IDD_AT_USE_CUSTOM, BST_CHECKED);
  997. SetDlgItemText(hDlg, IDD_AT_CUSTOM_ACCT_NAME, wszAccount);
  998. EnableAtAccountControls(hDlg, TRUE);
  999. }
  1000. }
  1001. else
  1002. {
  1003. SchedUIMessageDialog(hDlg,
  1004. IERR_GETATACCOUNT,
  1005. MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL,
  1006. NULL);
  1007. EndDialog(hDlg, 0);
  1008. }
  1009. }
  1010. //+---------------------------------------------------------------------------
  1011. //
  1012. // Function: HandleAtAccountChange
  1013. //
  1014. // Synopsis: Make the At account reflect the current settings in the
  1015. // dialog, and end the dialog if successful.
  1016. //
  1017. // Arguments: [hDlg] - handle to dialog
  1018. //
  1019. // History: 09-19-96 DavidMun Created
  1020. //
  1021. //----------------------------------------------------------------------------
  1022. VOID
  1023. HandleAtAccountChange(HWND hDlg)
  1024. {
  1025. HRESULT hr = S_OK;
  1026. WCHAR wszAccountName[MAX_USERNAME + 1] = TEXT("");
  1027. WCHAR wszPassword[MAX_PASSWORD + 1] = TEXT("");
  1028. WCHAR wszConfirmedPassword[MAX_PASSWORD + 1] = TEXT("");
  1029. do
  1030. {
  1031. //
  1032. // See if user just wants at jobs to run as localsystem
  1033. //
  1034. if (IsDlgButtonChecked(hDlg, IDD_AT_USE_SYSTEM) == BST_CHECKED)
  1035. {
  1036. hr = SetNetScheduleAccountInformation(NULL, NULL, wszPassword);
  1037. if (FAILED(hr))
  1038. {
  1039. SecurityErrorDialog(hDlg, hr);
  1040. }
  1041. else
  1042. {
  1043. EndDialog(hDlg, 0);
  1044. }
  1045. break;
  1046. }
  1047. //
  1048. // No, we have to validate account and password controls. Get the
  1049. // account name and fail if it's empty.
  1050. //
  1051. GetDlgItemText(hDlg,
  1052. IDD_AT_CUSTOM_ACCT_NAME,
  1053. wszAccountName,
  1054. MAX_USERNAME + 1);
  1055. if (wszAccountName[0] == L'\0')
  1056. {
  1057. SchedUIErrorDialog(hDlg, IERR_ACCOUNTNAME, (LPTSTR)NULL);
  1058. break;
  1059. }
  1060. //
  1061. // Get the passwords and fail if they haven't been changed, or if
  1062. // they don't match eachother.
  1063. //
  1064. GetDlgItemText(hDlg,
  1065. IDD_AT_PASSWORD,
  1066. wszPassword,
  1067. MAX_PASSWORD + 1);
  1068. GetDlgItemText(hDlg,
  1069. IDD_AT_CONFIRM_PASSWORD,
  1070. wszConfirmedPassword,
  1071. MAX_PASSWORD + 1);
  1072. if (lstrcmp(wszPassword, wszConfirmedPassword) != 0)
  1073. {
  1074. SchedUIErrorDialog(hDlg, IERR_PASSWORD, (LPTSTR)NULL);
  1075. break;
  1076. }
  1077. //
  1078. // Account name and passwords valid (as far as we can tell). Make
  1079. // the change to the account.
  1080. //
  1081. hr = SetNetScheduleAccountInformation(NULL, // local machine
  1082. wszAccountName,
  1083. wszPassword);
  1084. if (FAILED(hr))
  1085. {
  1086. SecurityErrorDialog(hDlg, hr);
  1087. }
  1088. else
  1089. {
  1090. EndDialog(hDlg, 0);
  1091. }
  1092. } while (0);
  1093. SecureZeroMemory(wszPassword, sizeof wszPassword);
  1094. SecureZeroMemory(wszConfirmedPassword, sizeof wszPassword);
  1095. }
  1096. //+---------------------------------------------------------------------------
  1097. //
  1098. // Function: SetAtAccountDlgProc
  1099. //
  1100. // Synopsis: Allow the user to specify which account to run AT jobs under
  1101. //
  1102. // Arguments: standard dialog proc
  1103. //
  1104. // Returns: standard dialog proc
  1105. //
  1106. // History: 09-19-96 DavidMun Created
  1107. //
  1108. //----------------------------------------------------------------------------
  1109. INT_PTR APIENTRY
  1110. SetAtAccountDlgProc(
  1111. HWND hDlg,
  1112. UINT uMsg,
  1113. WPARAM wParam,
  1114. LPARAM lParam)
  1115. {
  1116. BOOL fHandled = TRUE;
  1117. //
  1118. // Note: the DWLP_USER long is used as a dirty flag. If the user hits OK
  1119. // without having modified the edit controls or hit the radio buttons,
  1120. // then we'll just treat it as a Cancel if the dirty flag is FALSE.
  1121. //
  1122. switch (uMsg)
  1123. {
  1124. case WM_INITDIALOG:
  1125. InitAtAccountDlg(hDlg);
  1126. SetWindowLongPtr(hDlg, DWLP_USER, FALSE);
  1127. break; // return TRUE so windows will set focus
  1128. case WM_COMMAND:
  1129. switch(LOWORD(wParam))
  1130. {
  1131. case IDD_AT_USE_SYSTEM:
  1132. EnableAtAccountControls(hDlg, FALSE);
  1133. SetWindowLongPtr(hDlg, DWLP_USER, TRUE);
  1134. break;
  1135. case IDD_AT_USE_CUSTOM:
  1136. {
  1137. WCHAR wszUserName[MAX_USERNAME + 1];
  1138. DWORD cchUserName = MAX_USERNAME + 1;
  1139. SetWindowLongPtr(hDlg, DWLP_USER, TRUE);
  1140. //
  1141. // If there's nothing in the user account field, make it default
  1142. // to the logged-on user.
  1143. //
  1144. if (!GetDlgItemText(hDlg,
  1145. IDD_AT_CUSTOM_ACCT_NAME,
  1146. wszUserName,
  1147. cchUserName))
  1148. {
  1149. GetDefaultDomainAndUserName(wszUserName, cchUserName);
  1150. SetDlgItemText(hDlg, IDD_AT_CUSTOM_ACCT_NAME, wszUserName);
  1151. }
  1152. EnableAtAccountControls(hDlg, TRUE);
  1153. break;
  1154. }
  1155. case IDD_AT_CUSTOM_ACCT_NAME:
  1156. case IDD_AT_PASSWORD:
  1157. case IDD_AT_CONFIRM_PASSWORD:
  1158. if (EN_CHANGE == HIWORD(wParam))
  1159. {
  1160. SetWindowLongPtr(hDlg, DWLP_USER, TRUE);
  1161. }
  1162. else
  1163. {
  1164. fHandled = FALSE;
  1165. }
  1166. break;
  1167. case IDOK:
  1168. if (GetWindowLongPtr(hDlg, DWLP_USER))
  1169. {
  1170. //
  1171. // Do NOT clear the dirty flag here--if HandleAtAccountChange
  1172. // is successful, the dialog will end, but if not we need to
  1173. // retain the dirty state.
  1174. //
  1175. CWaitCursor WaitCursor;
  1176. HandleAtAccountChange(hDlg);
  1177. break;
  1178. }
  1179. // else FALL THROUGH
  1180. case IDCANCEL:
  1181. EndDialog(hDlg, wParam);
  1182. break;
  1183. default:
  1184. fHandled = FALSE;
  1185. break;
  1186. }
  1187. break;
  1188. default:
  1189. fHandled = FALSE;
  1190. break;
  1191. }
  1192. return fHandled;
  1193. }
  1194. //____________________________________________________________________________
  1195. //
  1196. // Member: CJobFolder::_JobsFVCallBack
  1197. //
  1198. // Arguments: [psvOuter] -- IN
  1199. // [psf] -- IN
  1200. // [hwndOwner] -- IN
  1201. // [uMsg] -- IN
  1202. // [wParam] -- IN
  1203. // [lParam] -- IN
  1204. //
  1205. // Returns: HRESULT
  1206. //
  1207. // History: 1/5/1996 RaviR Created
  1208. //
  1209. //____________________________________________________________________________
  1210. HRESULT CALLBACK
  1211. CJobFolder::_JobsFVCallBack(
  1212. LPSHELLVIEW psvOuter,
  1213. LPSHELLFOLDER psf,
  1214. HWND hwndOwner,
  1215. UINT uMsg,
  1216. WPARAM wParam,
  1217. LPARAM lParam)
  1218. {
  1219. DEBUG_OUT((DEB_USER12, "_JobsFVCallBack<uMsg=%d>\n", uMsg));
  1220. HRESULT hr = S_OK;
  1221. LRESULT lr = ERROR_SUCCESS;
  1222. switch(uMsg)
  1223. {
  1224. case DVM_GETCCHMAX:
  1225. {
  1226. UINT * pcchMax = (UINT *)lParam;
  1227. // <folder path> + '\' + cchMax + '.job' + null <= MAX_PATH
  1228. *pcchMax = MAX_PATH - (lstrlen(m_pszFolderPath) + 6);
  1229. break;
  1230. }
  1231. case DVM_DEFITEMCOUNT:
  1232. //
  1233. // If DefView times out enumerating items, let it know we probably only
  1234. // have about 20 items
  1235. //
  1236. *(int *)lParam = 20;
  1237. break;
  1238. case DVM_MERGEMENU:
  1239. {
  1240. m_qcm = *((LPQCMINFO)lParam);
  1241. UtMergeMenu(g_hInstance, POPUP_ADVANCED, POPUP_JOBS_MAIN_POPUPMERGE,
  1242. (LPQCMINFO)lParam);
  1243. break;
  1244. }
  1245. case DVM_INITMENUPOPUP:
  1246. {
  1247. UINT idCmdFirst = LOWORD(wParam);
  1248. UINT nIndex = HIWORD(wParam);
  1249. HMENU hmenu = (HMENU)lParam;
  1250. UINT idCmd = GetMenuItemID(hmenu, 0) - idCmdFirst;
  1251. if (idCmd == FSIDM_STOP_SCHED)
  1252. {
  1253. if (!UserCanChangeService(m_pszMachine))
  1254. {
  1255. //
  1256. // The job folder is on a remote machine, or we're on NT
  1257. // and the user is not an administrator. Disable stop,
  1258. // pause, and at account options and get out.
  1259. //
  1260. EnableMenuItem(hmenu, FSIDM_STOP_SCHED+idCmdFirst,
  1261. MF_DISABLED | MF_GRAYED);
  1262. EnableMenuItem(hmenu, FSIDM_PAUSE_SCHED+idCmdFirst,
  1263. MF_DISABLED | MF_GRAYED);
  1264. EnableMenuItem(hmenu, FSIDM_NOTIFY_MISSED+idCmdFirst,
  1265. MF_DISABLED | MF_GRAYED);
  1266. EnableMenuItem(hmenu, FSIDM_AT_ACCOUNT+idCmdFirst,
  1267. MF_DISABLED | MF_GRAYED);
  1268. break;
  1269. }
  1270. DWORD dwState;
  1271. hr = GetSchSvcState(dwState);
  1272. DEBUG_OUT((DEB_USER1, "Service state = %d\n", dwState));
  1273. if (FAILED(hr))
  1274. {
  1275. dwState = SERVICE_STOPPED;
  1276. }
  1277. UINT uiStartID = IDS_MI_STOP;
  1278. UINT uiPauseID = IDS_MI_PAUSE;
  1279. UINT uiPauseEnable = MFS_ENABLED;
  1280. #define CCH_MENU_TEXT 80
  1281. TCHAR tszStart[CCH_MENU_TEXT];
  1282. TCHAR tszPause[CCH_MENU_TEXT];
  1283. if (dwState == SERVICE_STOPPED ||
  1284. dwState == SERVICE_STOP_PENDING)
  1285. {
  1286. uiStartID = IDS_MI_START;
  1287. uiPauseEnable = MFS_DISABLED;
  1288. }
  1289. else if (dwState == SERVICE_PAUSED ||
  1290. dwState == SERVICE_PAUSE_PENDING)
  1291. {
  1292. uiPauseID = IDS_MI_CONTINUE;
  1293. }
  1294. if (dwState == SERVICE_START_PENDING)
  1295. {
  1296. uiPauseEnable = MFS_DISABLED;
  1297. }
  1298. MENUITEMINFO mii = {0};
  1299. mii.cbSize = sizeof(MENUITEMINFO);
  1300. mii.fMask = MIIM_TYPE;
  1301. LoadString(g_hInstance, uiStartID, tszStart, CCH_MENU_TEXT);
  1302. mii.dwTypeData = tszStart;
  1303. SetMenuItemInfo(hmenu, FSIDM_STOP_SCHED+idCmdFirst, FALSE,
  1304. &mii);
  1305. mii.fMask = MIIM_TYPE | MIIM_STATE;
  1306. LoadString(g_hInstance, uiPauseID, tszPause, CCH_MENU_TEXT);
  1307. mii.dwTypeData = tszPause;
  1308. mii.fState = uiPauseEnable;
  1309. SetMenuItemInfo(hmenu, FSIDM_PAUSE_SCHED+idCmdFirst, FALSE,
  1310. &mii);
  1311. CheckMenuItem(hmenu,
  1312. FSIDM_NOTIFY_MISSED+idCmdFirst,
  1313. g_fNotifyMiss ? MF_CHECKED : MF_UNCHECKED);
  1314. EnableMenuItem(hmenu,
  1315. FSIDM_AT_ACCOUNT+idCmdFirst,
  1316. MFS_ENABLED == uiPauseEnable ?
  1317. MF_ENABLED : MF_DISABLED | MF_GRAYED);
  1318. }
  1319. break;
  1320. }
  1321. case DVM_INVOKECOMMAND:
  1322. {
  1323. HMENU &hmenu = m_qcm.hmenu;
  1324. UINT id = (UINT)wParam + m_qcm.idCmdFirst;
  1325. DWORD dwState;
  1326. hr = GetSchSvcState(dwState);
  1327. if (FAILED(hr))
  1328. {
  1329. dwState = SERVICE_STOPPED;
  1330. }
  1331. switch (wParam)
  1332. {
  1333. case FSIDM_SORTBYNAME:
  1334. ShellFolderView_ReArrange(hwndOwner, COLUMN_NAME);
  1335. break;
  1336. case FSIDM_SORTBYSCHEDULE:
  1337. ShellFolderView_ReArrange(hwndOwner, COLUMN_SCHEDULE);
  1338. break;
  1339. case FSIDM_SORTBYNEXTRUNTIME:
  1340. ShellFolderView_ReArrange(hwndOwner, COLUMN_NEXTRUNTIME);
  1341. break;
  1342. case FSIDM_SORTBYLASTRUNTIME:
  1343. ShellFolderView_ReArrange(hwndOwner, COLUMN_LASTRUNTIME);
  1344. break;
  1345. case FSIDM_SORTBYSTATUS:
  1346. ShellFolderView_ReArrange(hwndOwner, COLUMN_STATUS);
  1347. break;
  1348. case FSIDM_SORTBYLASTEXITCODE:
  1349. ShellFolderView_ReArrange(hwndOwner, COLUMN_LASTEXITCODE);
  1350. break;
  1351. case FSIDM_SORTBYCREATOR:
  1352. ShellFolderView_ReArrange(hwndOwner, COLUMN_CREATOR);
  1353. break;
  1354. case FSIDM_NEWJOB:
  1355. if (UserCanChangeService(m_pszMachine))
  1356. {
  1357. PromptForServiceStart(hwndOwner);
  1358. }
  1359. hr = CreateAJobForApp(NULL);
  1360. break;
  1361. case FSIDM_STOP_SCHED:
  1362. if (dwState == SERVICE_STOPPED ||
  1363. dwState == SERVICE_STOP_PENDING)
  1364. {
  1365. hr = StartScheduler();
  1366. if (FAILED(hr))
  1367. {
  1368. SchedUIErrorDialog(hwndOwner, IERR_STARTSVC, (LPTSTR) NULL);
  1369. }
  1370. }
  1371. else
  1372. {
  1373. hr = StopScheduler();
  1374. if (FAILED(hr))
  1375. {
  1376. SchedUIErrorDialog(hwndOwner, IERR_STOPSVC, (LPTSTR) NULL);
  1377. }
  1378. }
  1379. break;
  1380. case FSIDM_PAUSE_SCHED:
  1381. hr = PauseScheduler(dwState != SERVICE_PAUSED &&
  1382. dwState != SERVICE_PAUSE_PENDING);
  1383. break;
  1384. case FSIDM_AT_ACCOUNT:
  1385. {
  1386. ULONG_PTR lpCookie = NULL;
  1387. if (ActivateActCtx(g_hActCtx, &lpCookie))
  1388. {
  1389. DialogBox(g_hInstance,
  1390. MAKEINTRESOURCE(IDD_AT_ACCOUNT_DLG),
  1391. hwndOwner,
  1392. SetAtAccountDlgProc);
  1393. DeactivateActCtx(0, lpCookie);
  1394. }
  1395. else
  1396. {
  1397. DialogBox(g_hInstance,
  1398. MAKEINTRESOURCE(IDD_AT_ACCOUNT_DLG),
  1399. hwndOwner,
  1400. SetAtAccountDlgProc);
  1401. }
  1402. }
  1403. break;
  1404. case FSIDM_NOTIFY_MISSED:
  1405. {
  1406. LONG lErr;
  1407. HKEY hSchedKey = NULL;
  1408. lErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1409. SCH_AGENT_KEY,
  1410. 0,
  1411. KEY_SET_VALUE,
  1412. &hSchedKey);
  1413. if (lErr != ERROR_SUCCESS)
  1414. {
  1415. DEBUG_OUT((DEB_ERROR, "RegOpenKeyEx of Scheduler key %uL\n", lErr));
  1416. break;
  1417. }
  1418. // Toggle the global var state
  1419. g_fNotifyMiss = !g_fNotifyMiss;
  1420. // Persist the change in the registry
  1421. ULONG cbData = sizeof(g_fNotifyMiss);
  1422. lErr = RegSetValueEx(hSchedKey,
  1423. SCH_NOTIFYMISS_VALUE,
  1424. 0,
  1425. REG_DWORD,
  1426. (LPBYTE) &g_fNotifyMiss,
  1427. cbData);
  1428. RegCloseKey(hSchedKey);
  1429. // If the change couldn't be persisted, undo it.
  1430. if (lErr != ERROR_SUCCESS)
  1431. {
  1432. DEBUG_OUT((DEB_ERROR, "RegSetValueEx of notify miss %uL\n", lErr));
  1433. g_fNotifyMiss = !g_fNotifyMiss;
  1434. }
  1435. break;
  1436. }
  1437. case FSIDM_VIEW_LOG:
  1438. OnViewLog(m_pszMachine, hwndOwner);
  1439. break;
  1440. default:
  1441. DEBUG_OUT((DEB_ERROR, "Unknown DVM_INVOKECOMMAND<%u>\n",wParam));
  1442. hr = E_FAIL;
  1443. }
  1444. break;
  1445. }
  1446. case DVM_GETTOOLTIPTEXT:
  1447. case DVM_GETHELPTEXT:
  1448. {
  1449. UINT idCmd = (UINT)LOWORD(wParam);
  1450. UINT cchMax = (UINT)HIWORD(wParam);
  1451. UINT uiToggle = 0;
  1452. LPSTR pszText = (LPSTR)lParam;
  1453. if (idCmd == FSIDM_STOP_SCHED || idCmd == FSIDM_PAUSE_SCHED)
  1454. {
  1455. DWORD dwState;
  1456. hr = GetSchSvcState(dwState);
  1457. if (FAILED(hr))
  1458. {
  1459. dwState = SERVICE_STOPPED;
  1460. }
  1461. if ((dwState == SERVICE_STOPPED ||
  1462. dwState == SERVICE_STOP_PENDING) &&
  1463. idCmd == FSIDM_STOP_SCHED)
  1464. {
  1465. uiToggle = MH_TEXT_TOGGLE;
  1466. }
  1467. else
  1468. {
  1469. if ((dwState == SERVICE_PAUSED ||
  1470. dwState == SERVICE_PAUSE_PENDING) &&
  1471. idCmd == FSIDM_PAUSE_SCHED)
  1472. {
  1473. uiToggle = MH_TEXT_TOGGLE;
  1474. }
  1475. }
  1476. }
  1477. LoadString(g_hInstance, idCmd + IDS_MH_FSIDM_FIRST + uiToggle,
  1478. (LPTSTR)pszText, cchMax);
  1479. break;
  1480. }
  1481. case DVM_DIDDRAGDROP:
  1482. {
  1483. DEBUG_OUT((DEB_USER12, "DVM_DIDDRAGDROP\n"));
  1484. // DWORD dwEffect = wParam;
  1485. // IDataObject * pdtobj = (IDataObject *)lParam;
  1486. //
  1487. // if (!(dwEffect & DROPEFFECT_MOVE))
  1488. // {
  1489. // DEBUG_OUT((DEB_USER1, "DVM_DIDDRAGDROP<Copy>\n"));
  1490. // }
  1491. // else
  1492. // {
  1493. // DEBUG_OUT((DEB_USER1, "DVM_DIDDRAGDROP<Move>\n"));
  1494. // }
  1495. break;
  1496. }
  1497. case DVM_GETWORKINGDIR:
  1498. {
  1499. UINT uMax = (UINT)wParam;
  1500. LPTSTR pszDir = (LPTSTR)lParam;
  1501. StringCchCopy(pszDir, uMax, m_pszFolderPath);
  1502. break;
  1503. }
  1504. //
  1505. // DVM_INSERTITEM and DVM_DELETEITEM are not processed because the
  1506. // directory change notifications already provide this information.
  1507. //
  1508. // case DVM_INSERTITEM:
  1509. // {
  1510. // PJOBID pjid = (PJOBID)wParam;
  1511. // if (JF_IsValidID((LPCITEMIDLIST)pjid) == TRUE)
  1512. // {
  1513. // DEBUG_OUT((DEB_USER1, "DVM_INSERTITEM <%ws>\n", pjid->GetName()));
  1514. // }
  1515. // break;
  1516. // }
  1517. // case DVM_DELETEITEM:
  1518. // {
  1519. // PDVSELCHANGEINFO psci = (PDVSELCHANGEINFO)lParam;
  1520. //
  1521. // PJOBID pjid = (PJOBID)psci->lParamItem;
  1522. //
  1523. // if (pjid == NULL)
  1524. // {
  1525. // DEBUG_OUT((DEB_USER1, "DVM_DELETEITEM delete all items.\n"));
  1526. // }
  1527. // else if (JF_IsValidID((LPCITEMIDLIST)pjid) == TRUE)
  1528. // {
  1529. // DEBUG_OUT((DEB_USER1, "DVM_DELETEITEM <%ws>\n", pjid->GetName()));
  1530. // }
  1531. // break;
  1532. // }
  1533. case DVM_RELEASE:
  1534. {
  1535. DEBUG_OUT((DEB_USER1, "\tDVM_RELEASE\n"));
  1536. m_pShellView = NULL;
  1537. break;
  1538. }
  1539. case DVM_WINDOWCREATED:
  1540. {
  1541. //
  1542. // If we're opening on the local machine, make sure the sa.dat
  1543. // file is up to date.
  1544. //
  1545. if (!m_pszMachine)
  1546. {
  1547. CheckSaDat(m_pszFolderPath);
  1548. }
  1549. // Save current listview mode
  1550. m_ulListViewModeOnEntry = _GetChildListViewMode(hwndOwner);
  1551. // Register change notifications for the pidl of the Tasks dir
  1552. DEBUG_ASSERT(!m_hwndNotify);
  1553. m_hwndNotify = I_CreateNotifyWnd();
  1554. if (m_hwndNotify == NULL)
  1555. {
  1556. hr = E_OUTOFMEMORY;
  1557. break;
  1558. }
  1559. SendMessage(m_hwndNotify, STUBM_SETDATA, (WPARAM)this, 0);
  1560. if (m_pszFolderPath == NULL)
  1561. {
  1562. hr = _InitRest();
  1563. CHECK_HRESULT(hr);
  1564. BREAK_ON_FAIL(hr);
  1565. }
  1566. LPITEMIDLIST pidl;
  1567. hr = SHILCreateFromPath(m_pszFolderPath, &pidl, NULL);
  1568. CHECK_HRESULT(hr);
  1569. BREAK_ON_FAIL(hr);
  1570. SHChangeNotifyEntry fsne;
  1571. fsne.pidl = pidl;
  1572. fsne.fRecursive = FALSE;
  1573. int fSources = SHCNRF_ShellLevel | SHCNRF_InterruptLevel;
  1574. //| SHCNRF_NewDelivery;
  1575. LONG fEvents = SHCNE_DISKEVENTS | SHCNE_RENAMEITEM | SHCNE_CREATE |
  1576. SHCNE_UPDATEITEM | SHCNE_ATTRIBUTES | SHCNE_DELETE;
  1577. CDll::LockServer(TRUE);
  1578. m_uRegister = SHChangeNotifyRegister(m_hwndNotify, fSources, fEvents,
  1579. JF_FSNOTIFY, 1, &fsne);
  1580. if (!m_uRegister)
  1581. {
  1582. CDll::LockServer(FALSE);
  1583. DEBUG_OUT_LASTERROR;
  1584. }
  1585. break;
  1586. }
  1587. case DVM_WINDOWDESTROY:
  1588. {
  1589. //
  1590. // Restore the listview mode that we found on entry, unless the
  1591. // user has changed away from report mode.
  1592. //
  1593. if (m_ulListViewModeOnEntry != INVALID_LISTVIEW_STYLE &&
  1594. _GetChildListViewMode(hwndOwner) == LVS_REPORT)
  1595. {
  1596. _SetViewMode(hwndOwner, m_ulListViewModeOnEntry);
  1597. }
  1598. if (m_uRegister)
  1599. {
  1600. SHChangeNotifyDeregister(m_uRegister);
  1601. CDll::LockServer(FALSE);
  1602. m_uRegister = 0;
  1603. }
  1604. if (m_hwndNotify)
  1605. {
  1606. BOOL fOk = DestroyWindow(m_hwndNotify);
  1607. m_hwndNotify = NULL;
  1608. if (!fOk)
  1609. {
  1610. DEBUG_OUT_LASTERROR;
  1611. }
  1612. }
  1613. break;
  1614. }
  1615. case SFVM_GETHELPTOPIC:
  1616. {
  1617. SFVM_HELPTOPIC_DATA * phtd = (SFVM_HELPTOPIC_DATA*)lParam;
  1618. StringCchCopy(phtd->wszHelpFile, MAX_PATH, L"mstask.chm");
  1619. break;
  1620. }
  1621. default:
  1622. hr = E_FAIL;
  1623. #if DBG==1
  1624. JFDbgOutCallbackMsg(uMsg);
  1625. #endif // DBG==1
  1626. }
  1627. return hr;
  1628. }
  1629. //+--------------------------------------------------------------------------
  1630. //
  1631. // Member: CJobFolder::_SetViewMode
  1632. //
  1633. // Synopsis: Select the listview mode specified by [ulListViewStyle].
  1634. //
  1635. // Arguments: [hwndOwner] - explorer window handle
  1636. // [ulListViewStyle] - LVS_* in LVS_TYPEMASK.
  1637. //
  1638. // History: 07-25-1997 DavidMun Created
  1639. //
  1640. //---------------------------------------------------------------------------
  1641. void
  1642. CJobFolder::_SetViewMode(
  1643. HWND hwndOwner,
  1644. ULONG ulListViewStyle)
  1645. {
  1646. switch (ulListViewStyle)
  1647. {
  1648. case LVS_ICON:
  1649. PostMessage(hwndOwner, WM_COMMAND, VIEW_ICON_MENU_ID, 0);
  1650. break;
  1651. case LVS_REPORT:
  1652. PostMessage(hwndOwner, WM_COMMAND, VIEW_DETAILS_MENU_ID, 0);
  1653. break;
  1654. case LVS_SMALLICON:
  1655. PostMessage(hwndOwner, WM_COMMAND, VIEW_SMALLICON_MENU_ID, 0);
  1656. break;
  1657. case LVS_LIST:
  1658. PostMessage(hwndOwner, WM_COMMAND, VIEW_LIST_MENU_ID, 0);
  1659. break;
  1660. default:
  1661. DEBUG_OUT((DEB_ERROR,
  1662. "CJobFolder::_SetViewMode: invalid view mode 0x%x\n",
  1663. ulListViewStyle));
  1664. break;
  1665. }
  1666. }
  1667. //+--------------------------------------------------------------------------
  1668. //
  1669. // Function: EnumChildWindowCallback
  1670. //
  1671. // Synopsis: Fill hwnd pointed to by [lParam] with [hwnd] if [hwnd] has
  1672. // class WC_LISTVIEW.
  1673. //
  1674. //
  1675. // Arguments: [hwnd] - window to check
  1676. // [lParam] - pointer to HWND
  1677. //
  1678. // Returns: TRUE - continue enumeration
  1679. // FALSE - [hwnd] is listview, *(HWND*)[lParam] = [hwnd], stop
  1680. // enumerating
  1681. //
  1682. // Modifies: *(HWND*)[lParam]
  1683. //
  1684. // History: 07-25-1997 DavidMun Created
  1685. //
  1686. //---------------------------------------------------------------------------
  1687. BOOL CALLBACK
  1688. EnumChildWindowCallback(
  1689. HWND hwnd,
  1690. LPARAM lParam)
  1691. {
  1692. TCHAR tszClassName[80];
  1693. GetClassName(hwnd, tszClassName, ARRAYLEN(tszClassName));
  1694. if (!lstrcmpi(tszClassName, WC_LISTVIEW))
  1695. {
  1696. *(HWND *)lParam = hwnd;
  1697. return FALSE;
  1698. }
  1699. return TRUE;
  1700. }
  1701. //+--------------------------------------------------------------------------
  1702. //
  1703. // Member: CJobFolder::_GetChildListViewMode
  1704. //
  1705. // Synopsis: Return the LVS_* value representing the mode of the first
  1706. // child listview control found for [hwndOwner].
  1707. //
  1708. // Arguments: [hwndOwner] -
  1709. //
  1710. // Returns: LVS_ICON, LVS_SMALLICON, LVS_REPORT, LVS_LIST, or
  1711. // INVALID_LISTVIEW_STYLE.
  1712. //
  1713. // History: 07-25-1997 DavidMun Created
  1714. //
  1715. //---------------------------------------------------------------------------
  1716. ULONG
  1717. CJobFolder::_GetChildListViewMode(
  1718. HWND hwndOwner)
  1719. {
  1720. HWND hwnd = NULL;
  1721. EnumChildWindows(hwndOwner,
  1722. EnumChildWindowCallback,
  1723. (LPARAM)&hwnd);
  1724. if (!hwnd)
  1725. {
  1726. DEBUG_OUT((DEB_ERROR,
  1727. "_GetChildListViewMode: can't find child listview\n"));
  1728. return INVALID_LISTVIEW_STYLE;
  1729. }
  1730. LONG lStyle = GetWindowLong(hwnd, GWL_STYLE);
  1731. return lStyle & LVS_TYPEMASK;
  1732. }
  1733. BOOL
  1734. CJobFolder::_ObjectAlreadyPresent(
  1735. LPTSTR pszObj)
  1736. {
  1737. BOOL fPresent = FALSE;
  1738. PJOBID pjid;
  1739. LPTSTR pszName = PathFindFileName(pszObj);
  1740. LPTSTR pszExt = PathFindExtension(pszName);
  1741. TCHAR tcSave;
  1742. if (pszExt)
  1743. {
  1744. tcSave = *pszExt;
  1745. *pszExt = TEXT('\0');
  1746. }
  1747. int cObjs = (int) ShellFolderView_GetObjectCount(m_hwndOwner);
  1748. for (int i=0; i < cObjs; i++)
  1749. {
  1750. pjid = (PJOBID)ShellFolderView_GetObject(m_hwndOwner, i);
  1751. if (lstrcmpi(pjid->GetName(), pszName) == 0)
  1752. {
  1753. fPresent = TRUE;
  1754. break;
  1755. }
  1756. }
  1757. if (pszExt)
  1758. {
  1759. *pszExt = tcSave;
  1760. }
  1761. return fPresent;
  1762. }
  1763. LRESULT
  1764. CJobFolder::HandleFsNotify(
  1765. LONG lNotification,
  1766. LPCITEMIDLIST* ppidl)
  1767. {
  1768. HRESULT hr = S_OK;
  1769. CJobID jid;
  1770. LRESULT lr;
  1771. TCHAR from[MAX_PATH];
  1772. TCHAR to[MAX_PATH];
  1773. SHGetPathFromIDList(ppidl[0], from);
  1774. DEBUG_OUT((DEB_USER1, "First pidl<%ws>\n", from));
  1775. switch (lNotification)
  1776. {
  1777. case SHCNE_RENAMEITEM:
  1778. {
  1779. DEBUG_OUT((DEB_USER1, "SHCNE_RENAMEITEM\n"));
  1780. LPTSTR psFrom = PathFindFileName(from) - 1;
  1781. *psFrom = TEXT('\0');
  1782. SHGetPathFromIDList(ppidl[1], to);
  1783. DEBUG_OUT((DEB_USER1, "Second pidl<%ws>\n", to));
  1784. LPTSTR psTo = PathFindFileName(to) - 1;
  1785. *psTo = TEXT('\0');
  1786. BOOL fFromJF = (lstrcmpi(m_pszFolderPath, from) == 0);
  1787. BOOL fToJF = (lstrcmpi(m_pszFolderPath, to) == 0);
  1788. *psFrom = TEXT('\\');
  1789. *psTo = TEXT('\\');
  1790. if (fFromJF == FALSE)
  1791. {
  1792. if (fToJF == FALSE)
  1793. {
  1794. break; // Nothing to do with job folder
  1795. }
  1796. //
  1797. // ADD object
  1798. //
  1799. // First check if this object doesn't already exist in the UI
  1800. if (_ObjectAlreadyPresent(to) == FALSE)
  1801. {
  1802. hr = jid.Load(NULL, to);
  1803. CHECK_HRESULT(hr);
  1804. BREAK_ON_FAIL(hr);
  1805. _AddObject(&jid);
  1806. }
  1807. }
  1808. else
  1809. {
  1810. if (fToJF == TRUE)
  1811. {
  1812. // Rename
  1813. hr = jid.Load(NULL, to);
  1814. CHECK_HRESULT(hr);
  1815. BREAK_ON_FAIL(hr);
  1816. CJobID jidOld;
  1817. jidOld.LoadDummy(PathFindFileName(from));
  1818. hr = _UpdateObject(&jidOld, &jid);
  1819. }
  1820. else
  1821. {
  1822. // Delete
  1823. // Need to create a dummy jobid
  1824. jid.LoadDummy(PathFindFileName(from));
  1825. _RemoveObject(&jid);
  1826. }
  1827. }
  1828. break;
  1829. }
  1830. case SHCNE_CREATE:
  1831. {
  1832. DEBUG_OUT((DEB_USER1, "SHCNE_CREATE\n"));
  1833. if (_ObjectAlreadyPresent(from) == FALSE)
  1834. {
  1835. //
  1836. // Not present, so add it.
  1837. //
  1838. hr = jid.Load(NULL, from);
  1839. if (hr == S_FALSE)
  1840. {
  1841. //
  1842. // Task is hidden. Don't display it.
  1843. //
  1844. break;
  1845. }
  1846. CHECK_HRESULT(hr);
  1847. BREAK_ON_FAIL(hr);
  1848. hr = _AddObject(&jid);
  1849. }
  1850. break;
  1851. }
  1852. case SHCNE_DELETE:
  1853. DEBUG_OUT((DEB_USER1, "SHCNE_DELETE\n"));
  1854. jid.LoadDummy(from);
  1855. _RemoveObject(&jid);
  1856. break;
  1857. case SHCNE_UPDATEDIR:
  1858. DEBUG_OUT((DEB_USER1, "SHCNE_UPDATEDIR\n"));
  1859. this->OnUpdateDir();
  1860. break;
  1861. case SHCNE_UPDATEITEM:
  1862. DEBUG_OUT((DEB_USER1, "SHCNE_UPDATEITEM\n"));
  1863. hr = jid.Load(NULL, from);
  1864. if (hr == S_FALSE)
  1865. {
  1866. //
  1867. // Task is hidden. Don't display it. Always remove from the ID list
  1868. // to take care of the case where this notification was due to the
  1869. // task being hidden.
  1870. //
  1871. _RemoveObject(&jid);
  1872. break;
  1873. }
  1874. CHECK_HRESULT(hr);
  1875. BREAK_ON_FAIL(hr);
  1876. hr = _UpdateObject(&jid, &jid);
  1877. break;
  1878. default:
  1879. DEBUG_OUT((DEB_USER1, "JF_FSNOTIFY unprocessed <0x%x>\n", lNotification));
  1880. }
  1881. return 0L;
  1882. }
  1883. LRESULT
  1884. CALLBACK
  1885. NotifyWndProc(
  1886. HWND hWnd,
  1887. UINT iMessage,
  1888. WPARAM wParam,
  1889. LPARAM lParam)
  1890. {
  1891. DEBUG_OUT((DEB_USER12, "NWP<0x%x>\n", iMessage));
  1892. switch (iMessage)
  1893. {
  1894. case STUBM_SETDATA:
  1895. SetWindowLongPtr(hWnd, 0, wParam);
  1896. return TRUE;
  1897. case STUBM_GETDATA:
  1898. return GetWindowLongPtr(hWnd, 0);
  1899. case JF_FSNOTIFY:
  1900. {
  1901. CJobFolder * pjf = (CJobFolder*)GetWindowLongPtr(hWnd, 0);
  1902. if (pjf == NULL)
  1903. {
  1904. DEBUG_OUT((DEB_ERROR, "NotifyWndProc: NULL CJobFolder pointer\n"));
  1905. return FALSE;
  1906. }
  1907. pjf->HandleFsNotify((LONG)lParam, (LPCITEMIDLIST*)wParam);
  1908. return TRUE;
  1909. }
  1910. default:
  1911. return DefWindowProc(hWnd, iMessage, wParam, lParam);
  1912. }
  1913. }
  1914. TCHAR const c_szNotifyWindowClass[] = TEXT("JF Notify Window Class");
  1915. TCHAR const c_szNULL[] = TEXT("");
  1916. HWND
  1917. I_CreateNotifyWnd(void)
  1918. {
  1919. WNDCLASS wndclass;
  1920. if (!GetClassInfo(g_hInstance, c_szNotifyWindowClass, &wndclass))
  1921. {
  1922. wndclass.style = 0;
  1923. wndclass.lpfnWndProc = NotifyWndProc;
  1924. wndclass.cbClsExtra = 0;
  1925. wndclass.cbWndExtra = sizeof(PVOID) * 2;
  1926. wndclass.hInstance = g_hInstance;
  1927. wndclass.hIcon = NULL;
  1928. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  1929. wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  1930. wndclass.lpszMenuName = NULL;
  1931. wndclass.lpszClassName = c_szNotifyWindowClass;
  1932. if (!RegisterClass(&wndclass))
  1933. return NULL;
  1934. }
  1935. return CreateWindowEx(WS_EX_TOOLWINDOW, c_szNotifyWindowClass, c_szNULL,
  1936. WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
  1937. NULL, NULL, g_hInstance, NULL);
  1938. }
  1939. #if DBG==1
  1940. void
  1941. JFDbgOutCallbackMsg(
  1942. UINT uMsg)
  1943. {
  1944. #define PROCESS_MSG(M) \
  1945. case M: DEBUG_OUT((DEB_USER12, "UNPROCESSED msg<%s, %d>\n", #M, M)); break;
  1946. #define DONT_PROCESS_MSG(M) \
  1947. case M: break;
  1948. switch (uMsg)
  1949. {
  1950. DONT_PROCESS_MSG(DVM_GETHELPTEXT)
  1951. DONT_PROCESS_MSG(DVM_GETTOOLTIPTEXT)
  1952. DONT_PROCESS_MSG(DVM_GETBUTTONINFO)
  1953. DONT_PROCESS_MSG(DVM_GETBUTTONS)
  1954. DONT_PROCESS_MSG(DVM_INITMENUPOPUP)
  1955. DONT_PROCESS_MSG(DVM_SELCHANGE)
  1956. PROCESS_MSG(DVM_DRAWITEM)
  1957. DONT_PROCESS_MSG(DVM_MEASUREITEM)
  1958. DONT_PROCESS_MSG(DVM_EXITMENULOOP)
  1959. PROCESS_MSG(DVM_RELEASE)
  1960. DONT_PROCESS_MSG(DVM_GETCCHMAX)
  1961. PROCESS_MSG(DVM_FSNOTIFY)
  1962. DONT_PROCESS_MSG(DVM_WINDOWCREATED)
  1963. DONT_PROCESS_MSG(DVM_WINDOWDESTROY)
  1964. PROCESS_MSG(DVM_REFRESH)
  1965. DONT_PROCESS_MSG(DVM_SETFOCUS)
  1966. DONT_PROCESS_MSG(DVM_KILLFOCUS)
  1967. PROCESS_MSG(DVM_QUERYCOPYHOOK)
  1968. PROCESS_MSG(DVM_NOTIFYCOPYHOOK)
  1969. DONT_PROCESS_MSG(DVM_GETDETAILSOF)
  1970. DONT_PROCESS_MSG(DVM_COLUMNCLICK)
  1971. PROCESS_MSG(DVM_QUERYFSNOTIFY)
  1972. PROCESS_MSG(DVM_DEFITEMCOUNT)
  1973. PROCESS_MSG(DVM_DEFVIEWMODE)
  1974. PROCESS_MSG(DVM_UNMERGEMENU)
  1975. PROCESS_MSG(DVM_INSERTITEM)
  1976. PROCESS_MSG(DVM_DELETEITEM)
  1977. DONT_PROCESS_MSG(DVM_UPDATESTATUSBAR)
  1978. DONT_PROCESS_MSG(DVM_BACKGROUNDENUM)
  1979. PROCESS_MSG(DVM_GETWORKINGDIR)
  1980. DONT_PROCESS_MSG(DVM_GETCOLSAVESTREAM)
  1981. DONT_PROCESS_MSG(DVM_SELECTALL)
  1982. PROCESS_MSG(DVM_DIDDRAGDROP)
  1983. PROCESS_MSG(DVM_FOLDERISPARENT)
  1984. default:
  1985. DEBUG_OUT((DEB_USER12, "UNKNOWN message <%d> !!!!\n", uMsg));
  1986. }
  1987. }
  1988. #endif // DBG==1