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.

594 lines
16 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 1996.
  5. //
  6. // File: taskwiz.cxx
  7. //
  8. // Contents: Class which creates and invokes the 'create new task' wizard.
  9. //
  10. // Classes: CTaskWizard
  11. //
  12. // History: 5-20-1997 DavidMun Created
  13. //
  14. //---------------------------------------------------------------------------
  15. #include "..\pch\headers.hxx"
  16. #pragma hdrstop
  17. #include "myheaders.hxx"
  18. #include "..\folderui\jobidl.hxx"
  19. //
  20. // Types
  21. //
  22. // SFindWiz - passed to window enumeration function. BUGBUG when wizard
  23. // on remote machine is supported, the 'tszFocus' member should be the
  24. // server name. For now, it is just the path to the tasks folder.
  25. //
  26. struct SFindWiz
  27. {
  28. BOOL fFound;
  29. LPCTSTR tszFocus;
  30. };
  31. //
  32. // Globals
  33. //
  34. // g_msgFindWizard - private window message used to interrogate the wizard
  35. // dialog proc during the find operation.
  36. //
  37. // TEMPLATE_STR - string used to create private message, also used by
  38. // folderui code to identify the template icon.
  39. //
  40. UINT g_msgFindWizard;
  41. extern const TCHAR TEMPLATE_STR[];
  42. //
  43. // External references
  44. //
  45. extern HRESULT
  46. QuietStartContinueService(); // ..\folderui\schstate.cxx
  47. extern HRESULT
  48. JFGetDataObject(
  49. LPCTSTR pszFolderPath,
  50. LPCITEMIDLIST pidlFolder,
  51. UINT cidl,
  52. LPCITEMIDLIST * apidl,
  53. BOOL fCut,
  54. LPVOID * ppvObj);
  55. extern HRESULT
  56. DisplayJobProperties(
  57. LPDATAOBJECT pdtobj);
  58. //+--------------------------------------------------------------------------
  59. //
  60. // Member: CTaskWizard::CTaskWizard
  61. //
  62. // Synopsis: ctor
  63. //
  64. // Arguments: [ptszFolderPath] - path to tasks folder
  65. //
  66. // History: 5-12-1997 DavidMun Created
  67. //
  68. //---------------------------------------------------------------------------
  69. CTaskWizard::CTaskWizard(
  70. LPCTSTR ptszFolderPath,
  71. LPITEMIDLIST pidlFolder)
  72. {
  73. TRACE_CONSTRUCTOR(CTaskWizard);
  74. SecureZeroMemory(_apWizPages, sizeof _apWizPages);
  75. _fAdvanced = FALSE;
  76. _tszJobObjectFullPath[0] = TEXT('\0');
  77. _pTask = NULL;
  78. lstrcpyn(_tszFolderPath, ptszFolderPath, ARRAYLEN(_tszFolderPath));
  79. _pidlFolder = pidlFolder;
  80. #ifdef WIZARD97
  81. _fUse256ColorBmp = Is256ColorSupported();
  82. #endif // WIZARD97
  83. }
  84. //+--------------------------------------------------------------------------
  85. //
  86. // Member: CTaskWizard::~CTaskWizard
  87. //
  88. // Synopsis: dtor
  89. //
  90. // History: 5-19-1997 DavidMun Created
  91. //
  92. //---------------------------------------------------------------------------
  93. CTaskWizard::~CTaskWizard()
  94. {
  95. TRACE_DESTRUCTOR(CTaskWizard);
  96. if (_pTask)
  97. {
  98. _pTask->Release();
  99. }
  100. ILFree(_pidlFolder);
  101. }
  102. //+--------------------------------------------------------------------------
  103. //
  104. // Member: CTaskWizard::Launch, static
  105. //
  106. // Synopsis: Run the task wizard in a separate thread.
  107. //
  108. // Arguments: [ptszFolderPath] - path to tasks folder.
  109. //
  110. // Returns: HRESULT
  111. //
  112. // History: 5-19-1997 DavidMun Created
  113. //
  114. // Notes: If an instance of the wizard is already running for the
  115. // target machine, makes that the foreground window and
  116. // returns.
  117. //
  118. //---------------------------------------------------------------------------
  119. HRESULT
  120. CTaskWizard::Launch(
  121. LPCTSTR ptszFolderPath,
  122. LPCITEMIDLIST pidlFolder)
  123. {
  124. TRACE_FUNCTION(CTaskWizard::Launch);
  125. HRESULT hr = S_OK;
  126. CTaskWizard *pNewWiz = NULL;
  127. do
  128. {
  129. //
  130. // Start the service if it isn't running, or continue it if it is
  131. // paused. Since this is the wizard, do it on behalf of the user
  132. // without asking first.
  133. //
  134. // Continue on failure, since it is better to let the user at least
  135. // create the task, even if the service can't be started (user might
  136. // not have permission).
  137. //
  138. hr = QuietStartContinueService();
  139. CHECK_HRESULT(hr);
  140. //
  141. // Create a path string that CPropPage will store. This is the
  142. // full path to the tasks folder, with a trailing backslash. The
  143. // CPropPage will truncate at the last backslash, since most other
  144. // callers give it a task filename.
  145. //
  146. ULONG cchPath = lstrlen(ptszFolderPath);
  147. if (cchPath >= MAX_PATH - 1) // reserve space for trailing backslash
  148. {
  149. hr = E_INVALIDARG;
  150. DEBUG_OUT_HRESULT(hr);
  151. break;
  152. }
  153. TCHAR tszFolderPath[MAX_PATH + 1];
  154. StringCchCopy(tszFolderPath, MAX_PATH + 1, ptszFolderPath);
  155. tszFolderPath[cchPath] = TEXT('\\');
  156. tszFolderPath[cchPath + 1] = TEXT('\0');
  157. //
  158. // Look for an instance of the wizard running and focused on our
  159. // folder path. If one is found, it will make itself foreground
  160. // window, and we can quit.
  161. //
  162. hr = _FindWizard(tszFolderPath);
  163. if (hr == S_OK)
  164. {
  165. break;
  166. }
  167. //
  168. // No wizard is up for the current focus. Create a wizard object
  169. // and run it in a new thread.
  170. //
  171. LPITEMIDLIST pidlFolderCopy = ILClone(pidlFolder);
  172. if (!pidlFolderCopy)
  173. {
  174. hr = E_OUTOFMEMORY;
  175. DEBUG_OUT_HRESULT(hr);
  176. break;
  177. }
  178. pNewWiz = new CTaskWizard(tszFolderPath, pidlFolderCopy);
  179. if (!pNewWiz)
  180. {
  181. ILFree(pidlFolderCopy);
  182. hr = E_OUTOFMEMORY;
  183. DEBUG_OUT_HRESULT(hr);
  184. break;
  185. }
  186. HANDLE hThread;
  187. DWORD idThread;
  188. hThread = CreateThread(NULL,
  189. 0,
  190. _WizardThreadProc,
  191. (LPVOID) pNewWiz,
  192. 0,
  193. &idThread);
  194. if (!hThread)
  195. {
  196. delete pNewWiz;
  197. DEBUG_OUT_LASTERROR;
  198. hr = HRESULT_FROM_LASTERROR;
  199. break;
  200. }
  201. VERIFY(CloseHandle(hThread));
  202. } while (0);
  203. return hr;
  204. }
  205. //+--------------------------------------------------------------------------
  206. //
  207. // Member: CTaskWizard::_WizardThreadProc, static
  208. //
  209. // Synopsis: Displays the wizard (and optionally task property sheet)
  210. // using a separate thread.
  211. //
  212. // Arguments: [pvThis] - CTaskWizard pointer
  213. //
  214. // Returns: HRESULT
  215. //
  216. // History: 5-20-1997 DavidMun Created
  217. //
  218. // Notes: The wizard runs in a separate thread so the explorer ui
  219. // isn't stalled.
  220. //
  221. //---------------------------------------------------------------------------
  222. DWORD WINAPI
  223. CTaskWizard::_WizardThreadProc(
  224. LPVOID pvThis)
  225. {
  226. HRESULT hr = OleInitialize(NULL);
  227. if (FAILED(hr))
  228. {
  229. DEBUG_OUT_HRESULT(hr);
  230. return hr;
  231. }
  232. CTaskWizard *pThis = (CTaskWizard *)pvThis;
  233. __try
  234. {
  235. hr = pThis->_DoWizard();
  236. //
  237. // Once _DoWizard returns, the wizard property sheet has closed.
  238. //
  239. // If the user elected to see the new task's property sheet, then
  240. // _fAdvanced will be set, and the completion page should have
  241. // set a valid filename and interface pointer for the task.
  242. //
  243. // Open the property sheet while we're still in the thread.
  244. //
  245. if (SUCCEEDED(hr) && pThis->_fAdvanced)
  246. {
  247. DEBUG_ASSERT(pThis->_pTask);
  248. DEBUG_ASSERT(*pThis->_tszJobObjectFullPath);
  249. //
  250. // Since we want to see the security page if the object is on NT
  251. // on an NTFS partition, we'll have to call the version of
  252. // DisplayJobProperties that takes a data object.
  253. //
  254. // To get a data object describing the task object, we need an
  255. // itemid for the job, so create one.
  256. //
  257. CJobID jid;
  258. jid.LoadDummy(pThis->_tszJobObjectFullPath);
  259. LPCITEMIDLIST pidl = (LPCITEMIDLIST) &jid;
  260. LPDATAOBJECT pdo = NULL;
  261. TCHAR tszFolderPath[MAX_PATH + 1];
  262. StringCchCopy(tszFolderPath, MAX_PATH + 1, pThis->_tszFolderPath);
  263. LPTSTR ptszLastSlash = _tcsrchr(tszFolderPath, TEXT('\\'));
  264. if (ptszLastSlash && lstrlen(ptszLastSlash) == 1)
  265. {
  266. *ptszLastSlash = TEXT('\0');
  267. }
  268. hr = JFGetDataObject(tszFolderPath, // path to tasks dir
  269. pThis->_pidlFolder, // itemid of tasks folder
  270. 1, // one itemid in array
  271. &pidl, // namely, this one
  272. FALSE, // not doing cut/paste
  273. (VOID **) &pdo);
  274. if (SUCCEEDED(hr))
  275. {
  276. hr = DisplayJobProperties(pdo);
  277. CHECK_HRESULT(hr);
  278. }
  279. else
  280. {
  281. DEBUG_OUT_HRESULT(hr);
  282. }
  283. }
  284. delete pThis;
  285. }
  286. __finally
  287. {
  288. OleUninitialize();
  289. }
  290. return (DWORD) hr;
  291. }
  292. //+--------------------------------------------------------------------------
  293. //
  294. // Member: CTaskWizard::_DoWizard
  295. //
  296. // Synopsis: Create the wizard pages and invoke the wizard.
  297. //
  298. // Returns: HRESULT
  299. //
  300. // History: 5-20-1997 DavidMun Created
  301. //
  302. // Notes: If wizard is successfully created, doesn't return until
  303. // user hits Cancel or Finish.
  304. //
  305. //---------------------------------------------------------------------------
  306. HRESULT
  307. CTaskWizard::_DoWizard()
  308. {
  309. TRACE_METHOD(CTaskWizard, _DoWizard);
  310. HRESULT hr = S_OK;
  311. UINT i = 0;
  312. HPROPSHEETPAGE ahpsp[NUM_TASK_WIZARD_PAGES];
  313. SecureZeroMemory(ahpsp, sizeof(ahpsp));
  314. do
  315. {
  316. //
  317. // Create all the wizard pages
  318. //
  319. _apWizPages[TWP_WELCOME ] = new CWelcomePage (this, _tszFolderPath, &ahpsp[TWP_WELCOME ]);
  320. _apWizPages[TWP_SELECT_PROGRAM] = new CSelectProgramPage(this, _tszFolderPath, &ahpsp[TWP_SELECT_PROGRAM]);
  321. _apWizPages[TWP_SELECT_TRIGGER] = new CSelectTriggerPage(this, _tszFolderPath, &ahpsp[TWP_SELECT_TRIGGER]);
  322. _apWizPages[TWP_DAILY ] = new CDailyPage (this, _tszFolderPath, &ahpsp[TWP_DAILY ]);
  323. _apWizPages[TWP_WEEKLY ] = new CWeeklyPage (this, _tszFolderPath, &ahpsp[TWP_WEEKLY ]);
  324. _apWizPages[TWP_MONTHLY ] = new CMonthlyPage (this, _tszFolderPath, &ahpsp[TWP_MONTHLY ]);
  325. _apWizPages[TWP_ONCE ] = new COncePage (this, _tszFolderPath, &ahpsp[TWP_ONCE ]);
  326. _apWizPages[TWP_PASSWORD ] = new CPasswordPage (this, _tszFolderPath, &ahpsp[TWP_PASSWORD ]);
  327. _apWizPages[TWP_COMPLETION ] = new CCompletionPage (this, _tszFolderPath, &ahpsp[TWP_COMPLETION ]);
  328. //
  329. // Check that all objects and pages could be created
  330. //
  331. for (i = 0; i < NUM_TASK_WIZARD_PAGES; i++)
  332. {
  333. if (!_apWizPages[i] || !ahpsp[i])
  334. {
  335. hr = E_OUTOFMEMORY;
  336. break;
  337. }
  338. }
  339. //
  340. // Manually destroy the pages if one could not be created, then exit
  341. //
  342. if (FAILED(hr))
  343. {
  344. DEBUG_OUT((DEB_ERROR, "Creation failed, destroying pages\n"));
  345. for (i = 0; i < NUM_TASK_WIZARD_PAGES; i++)
  346. {
  347. if (ahpsp[i])
  348. {
  349. VERIFY(DestroyPropertySheetPage(ahpsp[i]));
  350. }
  351. else if (_apWizPages[i])
  352. {
  353. delete _apWizPages[i];
  354. }
  355. }
  356. break;
  357. }
  358. //
  359. // All pages created, display the wizard
  360. //
  361. PROPSHEETHEADER psh;
  362. SecureZeroMemory(&psh, sizeof(psh));
  363. #ifdef WIZARD97
  364. psh.dwFlags = PSH_WIZARD | PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER;
  365. psh.pszbmWatermark = _fUse256ColorBmp ? MAKEINTRESOURCE(IDB_WATERMARK256) : MAKEINTRESOURCE(IDB_WATERMARK16);
  366. psh.pszbmHeader = _fUse256ColorBmp ? MAKEINTRESOURCE(IDB_BANNER256) : MAKEINTRESOURCE(IDB_BANNER16);
  367. #else
  368. psh.dwFlags = PSH_WIZARD;
  369. #endif // WIZARD97
  370. psh.dwSize = sizeof(psh);
  371. psh.hInstance = g_hInstance;
  372. psh.hwndParent = NULL;
  373. psh.pszCaption = NULL; // ignored for wizards; see CWelcome init
  374. psh.phpage = ahpsp;
  375. psh.nStartPage = 0;
  376. psh.nPages = NUM_TASK_WIZARD_PAGES;
  377. if (PropertySheet(&psh) == -1)
  378. {
  379. hr = HRESULT_FROM_WIN32(GetLastError());
  380. DEBUG_OUT_HRESULT(hr);
  381. }
  382. } while (0);
  383. return hr;
  384. }
  385. //+--------------------------------------------------------------------------
  386. //
  387. // Function: FindWizardEnumWndProc
  388. //
  389. // Synopsis: EnumWindows callback used to search for a create new task
  390. // wizard opened on the specified focus.
  391. //
  392. // Arguments: [hwnd] - top level window handle
  393. // [lParam] - pointer to SFindWiz struct
  394. //
  395. // Returns: TRUE - not found, continue enumeration
  396. // FALSE - found wizard, quit enumerating
  397. //
  398. // Modifies: SFindWiz struct pointed to by [lParam]
  399. //
  400. // History: 5-20-1997 DavidMun Created
  401. //
  402. //---------------------------------------------------------------------------
  403. BOOL CALLBACK
  404. FindWizardEnumWndProc(
  405. HWND hwnd,
  406. LPARAM lParam)
  407. {
  408. SFindWiz *pfw = (SFindWiz *) lParam;
  409. ULONG pid;
  410. GetWindowThreadProcessId(hwnd, &pid);
  411. do
  412. {
  413. //
  414. // If the window isn't in this process (explorer.exe) then ignore
  415. // it.
  416. //
  417. if (pid != GetCurrentProcessId())
  418. {
  419. break;
  420. }
  421. //
  422. // If it isn't the dialog class, it can't be a wizard.
  423. //
  424. if (!IsDialogClass(hwnd))
  425. {
  426. break;
  427. }
  428. //
  429. // Found a dialog window that was created by this process. If it's
  430. // a wizard, then it should return a valid window which is also of
  431. // dialog class.
  432. //
  433. HWND hwndPage = PropSheet_GetCurrentPageHwnd(hwnd);
  434. if (!IsWindow(hwndPage) || !IsDialogClass(hwndPage))
  435. {
  436. break;
  437. }
  438. //
  439. // Could be a wizard page. Ask it if it's THE wizard for the
  440. // focus. Note it's only possible to get away with sending a pointer
  441. // in the message because we've guaranteed the window belongs to this
  442. // process.
  443. //
  444. ULONG ulResult = (ULONG)SendMessage(hwndPage,
  445. g_msgFindWizard,
  446. 0,
  447. (LPARAM) pfw->tszFocus);
  448. if (ulResult == g_msgFindWizard)
  449. {
  450. pfw->fFound = TRUE;
  451. }
  452. } while (0);
  453. return !pfw->fFound; // continue enumerating if not found
  454. }
  455. //+--------------------------------------------------------------------------
  456. //
  457. // Member: CTaskWizard::_FindWizard
  458. //
  459. // Synopsis: Search through top level windows to find a create new task
  460. // wizard which is focused on [ptszFolderPath].
  461. //
  462. // Arguments: [ptszFolderPath] - wizard focus
  463. //
  464. // Returns: S_OK - found
  465. // S_FALSE - not found
  466. //
  467. // History: 5-20-1997 DavidMun Created
  468. //
  469. // Notes: BUGBUG change ptszFolderPath to server name
  470. //
  471. //---------------------------------------------------------------------------
  472. HRESULT
  473. CTaskWizard::_FindWizard(
  474. LPCTSTR ptszFolderPath)
  475. {
  476. SFindWiz fw = { FALSE, ptszFolderPath };
  477. if (!g_msgFindWizard)
  478. {
  479. g_msgFindWizard = RegisterWindowMessage(TEMPLATE_STR);
  480. }
  481. EnumWindows(FindWizardEnumWndProc, (LPARAM) &fw);
  482. return fw.fFound ? S_OK : S_FALSE;
  483. }