Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

620 lines
15 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 1996.
  5. //
  6. // File: complete.cxx
  7. //
  8. // Contents: Task wizard completion (final) property page implementation.
  9. //
  10. // Classes: CCompletionPage
  11. //
  12. // History: 4-28-1997 DavidMun Created
  13. //
  14. //---------------------------------------------------------------------------
  15. #include "..\pch\headers.hxx"
  16. #pragma hdrstop
  17. #include "myheaders.hxx"
  18. //+--------------------------------------------------------------------------
  19. //
  20. // Member: CCompletionPage::CCompletionPage
  21. //
  22. // Synopsis: ctor
  23. //
  24. // Arguments: [ptszFolderPath] - full path to tasks folder with dummy
  25. // filename appended
  26. // [phPSP] - filled with prop page handle
  27. //
  28. // History: 4-28-1997 DavidMun Created
  29. //
  30. //---------------------------------------------------------------------------
  31. CCompletionPage::CCompletionPage(
  32. CTaskWizard *pParent,
  33. LPTSTR ptszFolderPath,
  34. HPROPSHEETPAGE *phPSP):
  35. CWizPage(MAKEINTRESOURCE(IDD_COMPLETION), ptszFolderPath)
  36. {
  37. TRACE_CONSTRUCTOR(CCompletionPage);
  38. _pParent = pParent;
  39. _hIcon = NULL;
  40. _pJob = NULL;
  41. #ifdef WIZARD97
  42. m_psp.dwFlags |= PSP_HIDEHEADER;
  43. #endif // WIZARD97
  44. *phPSP = CreatePropertySheetPage(&m_psp);
  45. if (!*phPSP)
  46. {
  47. DEBUG_OUT_LASTERROR;
  48. }
  49. }
  50. //+--------------------------------------------------------------------------
  51. //
  52. // Member: CCompletionPage::~CCompletionPage
  53. //
  54. // Synopsis: dtor
  55. //
  56. // History: 4-28-1997 DavidMun Created
  57. //
  58. //---------------------------------------------------------------------------
  59. CCompletionPage::~CCompletionPage()
  60. {
  61. TRACE_DESTRUCTOR(CCompletionPage);
  62. if (_pJob)
  63. {
  64. _pJob->Release();
  65. }
  66. if (_hIcon)
  67. {
  68. VERIFY(DestroyIcon(_hIcon));
  69. }
  70. }
  71. //===========================================================================
  72. //
  73. // CWizPage overrides
  74. //
  75. //===========================================================================
  76. //+--------------------------------------------------------------------------
  77. //
  78. // Member: CCompletionPage::_OnInitDialog
  79. //
  80. // Synopsis: Perform initialization that should only occur once.
  81. //
  82. // Arguments: [lParam] - LPPROPSHEETPAGE used to create this page
  83. //
  84. // Returns: TRUE (let windows set focus)
  85. //
  86. // History: 5-20-1997 DavidMun Created
  87. // 4-14-1998 CameronE Added Policy Support
  88. //
  89. //---------------------------------------------------------------------------
  90. LRESULT
  91. CCompletionPage::_OnInitDialog(
  92. LPARAM lParam)
  93. {
  94. TRACE_METHOD(CCompletionPage, _OnInitDialog);
  95. //
  96. // Policy Support - remove "open advanced" checkbox if
  97. // we find a registry key for that policy
  98. //
  99. if (RegReadPolicyKey(TS_KEYPOLICY_DISABLE_ADVANCED))
  100. {
  101. DEBUG_OUT((DEB_ITRACE, "Policy DISABLE_ADVANCED active to remove checkbox\n"));
  102. EnableWindow(_hCtrl(complete_advanced_ckbox), FALSE);
  103. ShowWindow(_hCtrl(complete_advanced_ckbox), SW_HIDE);
  104. }
  105. return TRUE;
  106. }
  107. //+--------------------------------------------------------------------------
  108. //
  109. // Member: CCompletionPage::_OnPSNSetActive
  110. //
  111. // Synopsis: Create a task object (in-memory only) and update the
  112. // summary information on this page.
  113. //
  114. // Arguments: [lParam] - LPNMHDR (unused)
  115. //
  116. // Returns: TRUE
  117. //
  118. // History: 5-20-1997 DavidMun Created
  119. //
  120. //---------------------------------------------------------------------------
  121. LRESULT
  122. CCompletionPage::_OnPSNSetActive(
  123. LPARAM lParam)
  124. {
  125. TRACE_METHOD(CCompletionPage, _OnPSNSetActive);
  126. HRESULT hr = S_OK;
  127. LPWSTR pwszTrigger = NULL;
  128. do
  129. {
  130. //
  131. // Update the summary info to reflect the user's latest
  132. // choices.
  133. //
  134. CSelectProgramPage *pSelProg = GetSelectProgramPage(_pParent);
  135. CSelectTriggerPage *pSelTrig = GetSelectTriggerPage(_pParent);
  136. HICON hIcon;
  137. hIcon = pSelProg->GetSelectedAppIcon();
  138. SendDlgItemMessage(Hwnd(),
  139. complete_task_icon,
  140. STM_SETICON,
  141. (WPARAM) hIcon,
  142. 0L);
  143. if (_hIcon)
  144. {
  145. VERIFY(DestroyIcon(_hIcon));
  146. }
  147. _hIcon = hIcon;
  148. Static_SetText(_hCtrl(complete_taskname_lbl), pSelTrig->GetTaskName());
  149. Static_SetText(_hCtrl(complete_trigger_lbl), TEXT(""));
  150. //
  151. // Create the task object so we can ask it for its trigger string.
  152. // The object won't be persisted until the user hits the Finish
  153. // button.
  154. //
  155. hr = _UpdateTaskObject();
  156. if (FAILED(hr))
  157. {
  158. _SetWizButtons(PSWIZB_BACK | PSWIZB_DISABLEDFINISH);
  159. break;
  160. }
  161. //
  162. // _pJob is now valid, so enable the finish button.
  163. //
  164. _SetWizButtons(PSWIZB_BACK | PSWIZB_FINISH);
  165. //
  166. // Put the trigger string in the ui so the user can see a
  167. // description of when the task will run.
  168. //
  169. hr = _pJob->GetTriggerString(0, &pwszTrigger);
  170. if (FAILED(hr))
  171. {
  172. DEBUG_OUT_HRESULT(hr);
  173. break;
  174. }
  175. #if defined(UNICODE)
  176. Static_SetText(_hCtrl(complete_trigger_lbl), pwszTrigger);
  177. #else
  178. TCHAR tszTrigger[SCH_XBIGBUF_LEN];
  179. hr = UnicodeToAnsi(tszTrigger, pwszTrigger, ARRAYLEN(tszTrigger));
  180. Static_SetText(_hCtrl(complete_trigger_lbl), tszTrigger);
  181. #endif // defined(UNICODE)
  182. } while (0);
  183. CoTaskMemFree(pwszTrigger);
  184. return CPropPage::_OnPSNSetActive(lParam);
  185. }
  186. //+--------------------------------------------------------------------------
  187. //
  188. // Member: CCompletionPage::_OnWizBack
  189. //
  190. // Synopsis: Set the current page to the one that should precede this.
  191. //
  192. // Returns: -1
  193. //
  194. // History: 5-20-1997 DavidMun Created
  195. //
  196. //---------------------------------------------------------------------------
  197. LRESULT
  198. CCompletionPage::_OnWizBack()
  199. {
  200. TRACE_METHOD(CCompletionPage, _OnWizBack);
  201. #if defined(_CHICAGO_)
  202. ULONG iddPage = GetSelectTriggerPage(_pParent)->GetSelectedTriggerPageID();
  203. SetWindowLongPtr(Hwnd(), DWLP_MSGRESULT, iddPage);
  204. #else
  205. SetWindowLongPtr(Hwnd(), DWLP_MSGRESULT, IDD_PASSWORD);
  206. #endif // defined(_CHICAGO_)
  207. return -1;
  208. }
  209. //+--------------------------------------------------------------------------
  210. //
  211. // Member: CCompletionPage::_OnWizFinish
  212. //
  213. // Synopsis: Persist the task object.
  214. //
  215. // Returns: 0
  216. //
  217. // History: 5-20-1997 DavidMun Created
  218. //
  219. //---------------------------------------------------------------------------
  220. LRESULT
  221. CCompletionPage::_OnWizFinish()
  222. {
  223. TRACE_METHOD(CCompletionPage, _OnWizFinish);
  224. HRESULT hr = S_OK;
  225. LPCTSTR ptszJob = NULL;
  226. CSelectTriggerPage *pSelTrig = GetSelectTriggerPage(_pParent);
  227. #if !defined(_CHICAGO_)
  228. CPasswordPage *pPasswdPage = GetPasswordPage(_pParent);
  229. #endif // !defined(_CHICAGO_)
  230. BOOL fSaveSucceeded = FALSE;
  231. do
  232. {
  233. if (!_pJob)
  234. {
  235. hr = E_OUTOFMEMORY;
  236. break;
  237. }
  238. //
  239. // Persist the new job object.
  240. //
  241. ptszJob = pSelTrig->GetJobObjectFullPath();
  242. CWaitCursor HourGlass;
  243. if (FileExists((LPTSTR)ptszJob))
  244. {
  245. if (!DeleteFile(ptszJob))
  246. {
  247. //
  248. // Complain but leave hr alone so we don't pop up a second
  249. // error
  250. //
  251. DEBUG_OUT_LASTERROR;
  252. SchedUIErrorDialog(Hwnd(),
  253. IDS_CANT_DELETE_EXISTING,
  254. (LPTSTR) pSelTrig->GetTaskName());
  255. break;
  256. }
  257. }
  258. #ifdef UNICODE
  259. hr = _pJob->Save(ptszJob, TRUE);
  260. #else
  261. WCHAR wszBuf[MAX_PATH];
  262. hr = AnsiToUnicode(wszBuf, ptszJob, MAX_PATH);
  263. BREAK_ON_FAIL_HRESULT(hr);
  264. hr = _pJob->Save(wszBuf, TRUE);
  265. #endif
  266. BREAK_ON_FAIL_HRESULT(hr);
  267. fSaveSucceeded = TRUE;
  268. #if !defined(_CHICAGO_)
  269. //
  270. // (NT only) set the account information. Caller must ensure
  271. // service is running.
  272. //
  273. hr = _pJob->SetAccountInformation(pPasswdPage->GetAccountName(),
  274. pPasswdPage->GetPassword());
  275. BREAK_ON_FAIL_HRESULT(hr);
  276. hr = _pJob->Save(NULL, FALSE);
  277. BREAK_ON_FAIL_HRESULT(hr);
  278. #endif // !defined(_CHICAGO_)
  279. } while (0);
  280. #if !defined(_CHICAGO_)
  281. //
  282. // Don't leave account name & password in memory
  283. //
  284. pPasswdPage->ZeroCredentials();
  285. #endif // !defined(_CHICAGO_)
  286. //
  287. // If advanced checkbox is checked, indicate to DoTaskWizard. Also,
  288. // give it a reference to the job object so it can do any terminal
  289. // processing necessary (e.g., displaying the property pages).
  290. //
  291. if (fSaveSucceeded)
  292. {
  293. BOOL fAdvanced = IsDlgButtonChecked(Hwnd(), complete_advanced_ckbox);
  294. _pParent->SetAdvancedMode(fAdvanced);
  295. _pJob->AddRef();
  296. _pParent->SetTaskObject(_pJob);
  297. _pParent->SetJobObjectPath(ptszJob);
  298. }
  299. //
  300. // Notify the user if anything went wrong.
  301. //
  302. if (FAILED(hr))
  303. {
  304. if (fSaveSucceeded)
  305. {
  306. SchedUIErrorDialog(Hwnd(), IDS_WIZFINISH_NONFATAL, hr);
  307. }
  308. else
  309. {
  310. SchedUIErrorDialog(Hwnd(), IDS_WIZFINISH_FATAL, hr);
  311. }
  312. }
  313. return 0;
  314. }
  315. //+--------------------------------------------------------------------------
  316. //
  317. // Member: CCompletionPage::_UpdateTaskObject
  318. //
  319. // Synopsis: Create a task object in memory that matches all the
  320. // settings the user made on previous pages.
  321. //
  322. // Returns: HRESULT
  323. //
  324. // History: 5-20-1997 DavidMun Created
  325. //
  326. // Notes: If a task object already exists, it is freed and replaced
  327. // with a new one.
  328. //
  329. // The task object is not persisted until the user hits the
  330. // finish button.
  331. //
  332. //---------------------------------------------------------------------------
  333. HRESULT
  334. CCompletionPage::_UpdateTaskObject()
  335. {
  336. TRACE_METHOD(CCompletionPage, _CreateTaskObject);
  337. HRESULT hr = S_OK;
  338. ITaskTrigger *pTrigger = NULL;
  339. CSelectTriggerPage *pSelTrig = GetSelectTriggerPage(_pParent);
  340. CSelectProgramPage *pSelProg = GetSelectProgramPage(_pParent);
  341. do
  342. {
  343. //
  344. // If there's already a task object, get rid of it. This would
  345. // be the case if the user got to the finish page, then hit
  346. // the back button.
  347. //
  348. if (_pJob)
  349. {
  350. _pJob->Release();
  351. _pJob = NULL;
  352. }
  353. //
  354. // Create the task object
  355. //
  356. _pJob = CJob::Create();
  357. if (_pJob == NULL)
  358. {
  359. hr = E_OUTOFMEMORY;
  360. DEBUG_OUT_HRESULT(hr);
  361. break;
  362. }
  363. //
  364. // Add default flags
  365. //
  366. DWORD dwAddFlags = TASK_FLAG_DONT_START_IF_ON_BATTERIES |
  367. TASK_FLAG_KILL_IF_GOING_ON_BATTERIES;
  368. hr = _pJob->SetFlags(dwAddFlags);
  369. BREAK_ON_FAIL_HRESULT(hr);
  370. //
  371. // Fill in the trigger struct
  372. //
  373. TASK_TRIGGER Trigger;
  374. ZeroMemory(&Trigger, sizeof(Trigger));
  375. Trigger.cbTriggerSize = sizeof(Trigger);
  376. CTriggerPage *pTriggerPage = pSelTrig->GetSelectedTriggerPage();
  377. if (pTriggerPage)
  378. {
  379. pTriggerPage->FillInTrigger(&Trigger);
  380. }
  381. else
  382. {
  383. ULONG idTrigger = pSelTrig->GetSelectedTriggerType();
  384. switch (idTrigger)
  385. {
  386. case seltrig_startup_rb:
  387. Trigger.TriggerType = TASK_EVENT_TRIGGER_AT_SYSTEMSTART;
  388. break;
  389. case seltrig_logon_rb:
  390. Trigger.TriggerType = TASK_EVENT_TRIGGER_AT_LOGON;
  391. break;
  392. default:
  393. DEBUG_ASSERT(FALSE);
  394. hr = E_UNEXPECTED;
  395. break;
  396. }
  397. BREAK_ON_FAIL_HRESULT(hr);
  398. SYSTEMTIME stStart;
  399. GetSystemTime(&stStart);
  400. Trigger.wBeginYear = stStart.wYear;
  401. Trigger.wBeginMonth = stStart.wMonth;
  402. Trigger.wBeginDay = stStart.wDay;
  403. }
  404. //
  405. // Create a trigger object and init it with the struct
  406. //
  407. WORD iTrigger = (WORD)-1;
  408. hr = _pJob->CreateTrigger(&iTrigger, &pTrigger);
  409. BREAK_ON_FAIL_HRESULT(hr);
  410. DEBUG_ASSERT(iTrigger == 0);
  411. hr = pTrigger->SetTrigger(&Trigger);
  412. BREAK_ON_FAIL_HRESULT(hr);
  413. //
  414. // Set the application name
  415. //
  416. TCHAR tszExeFullPath[MAX_PATH + 1];
  417. pSelProg->GetExeFullPath(tszExeFullPath, ARRAYLEN(tszExeFullPath));
  418. #ifdef UNICODE
  419. hr = _pJob->SetApplicationName(tszExeFullPath);
  420. #else
  421. WCHAR wszBuf[MAX_PATH + 1];
  422. hr = AnsiToUnicode(wszBuf, tszExeFullPath, ARRAYLEN(wszBuf));
  423. BREAK_ON_FAIL_HRESULT(hr);
  424. hr = _pJob->SetApplicationName(wszBuf);
  425. #endif
  426. BREAK_ON_FAIL_HRESULT(hr);
  427. //
  428. // Set the arguments
  429. //
  430. #ifdef UNICODE
  431. hr = _pJob->SetParameters(pSelProg->GetArgs());
  432. #else
  433. //
  434. // Since unicode is not defined, we're running on chicago, which
  435. // means that the app chosen might be sage-aware. If it is,
  436. // it will need a /sagerun:n argument.
  437. //
  438. // BUGBUG if the wizard is made remotable then this will need
  439. // to be performed while running on nt if the target is win9x.
  440. //
  441. TCHAR tszExeName[MAX_PATH + 1];
  442. int iSageParam;
  443. pSelProg->GetExeName(tszExeName, ARRAYLEN(tszExeName));
  444. LPCTSTR ptzArgs = pSelProg->GetArgs();
  445. if (IsSageAware(tszExeName, ptzArgs, &iSageParam) &&
  446. MAX_CCH_SAGERUN_PARAM + lstrlen(ptzArgs) < ARRAYLEN(wszBuf))
  447. {
  448. TCHAR tszBuf[MAX_PATH + 1];
  449. wsprintf(tszBuf,
  450. TEXT("%s %s%u"),
  451. pSelProg->GetArgs(),
  452. SAGERUN_PARAM,
  453. iSageParam);
  454. hr = AnsiToUnicode(wszBuf, tszBuf, ARRAYLEN(wszBuf));
  455. CreateSageRunKey(tszExeName, iSageParam);
  456. }
  457. else
  458. {
  459. hr = AnsiToUnicode(wszBuf, ptzArgs, ARRAYLEN(wszBuf));
  460. }
  461. BREAK_ON_FAIL_HRESULT(hr);
  462. hr = _pJob->SetParameters(wszBuf);
  463. #endif
  464. BREAK_ON_FAIL_HRESULT(hr);
  465. //
  466. // Set the working directory
  467. //
  468. TCHAR tszWorkingDir[MAX_PATH + 1];
  469. pSelProg->GetExeDir(tszWorkingDir, ARRAYLEN(tszWorkingDir));
  470. #ifdef UNICODE
  471. hr = _pJob->SetWorkingDirectory(tszWorkingDir);
  472. #else
  473. hr = AnsiToUnicode(wszBuf, tszWorkingDir, ARRAYLEN(wszBuf));
  474. BREAK_ON_FAIL_HRESULT(hr);
  475. hr = _pJob->SetWorkingDirectory(wszBuf);
  476. #endif
  477. BREAK_ON_FAIL_HRESULT(hr);
  478. } while (0);
  479. if (pTrigger)
  480. {
  481. pTrigger->Release();
  482. }
  483. return hr;
  484. }