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.

2480 lines
66 KiB

  1. //____________________________________________________________________________
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1996.
  5. //
  6. // File: general.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // Notes: For the first release of the scheduling agent, all security
  15. // operations are disabled under Win95, even Win95 to NT.
  16. //
  17. // History: 3/4/1996 RaviR Created
  18. // 1-30-1997 DavidMun params edit becomes working dir
  19. // 02/29/01 JBenton BUG 280401 app icon was not being updated
  20. // on prop sheet in case of service not running
  21. //
  22. //____________________________________________________________________________
  23. #include "..\pch\headers.hxx"
  24. #pragma hdrstop
  25. #include "..\inc\dll.hxx"
  26. #include "..\folderui\dbg.h"
  27. #include "..\folderui\macros.h"
  28. #include "dlg.hxx"
  29. #include "..\folderui\jobicons.hxx"
  30. #include "..\inc\resource.h"
  31. #include "..\inc\defines.hxx"
  32. #include "..\inc\common.hxx"
  33. #include "..\inc\misc.hxx"
  34. #include "..\inc\policy.hxx"
  35. #if !defined(_CHICAGO_)
  36. #define SECURITY_WIN32
  37. #include <security.h> // GetUserNameEx
  38. #undef SECURITY_WIN32
  39. #include "..\inc\network.hxx"
  40. #endif // !defined(_CHICAGO_)
  41. #include "rc.h"
  42. #include "defines.h"
  43. #include <mstask.h>
  44. #include "uiutil.hxx"
  45. #include "commdlg.h"
  46. #include "helpids.h"
  47. #include "iconhlpr.hxx"
  48. #include "schedui.hxx"
  49. #include "sageset.hxx"
  50. //
  51. // extern
  52. //
  53. extern HINSTANCE g_hInstance;
  54. #if !defined(_CHICAGO_)
  55. //
  56. // Forward references
  57. //
  58. // CenterDialog - Centers a dialog on screen. Used by the security-related
  59. // subdialogs.
  60. //
  61. void
  62. CenterDialog(HWND hDlg);
  63. void
  64. GetDefaultDomainAndUserName(
  65. LPTSTR ptszDomainAndUserName,
  66. ULONG cchBuf);
  67. //
  68. // Launches the modal set password dialog.
  69. //
  70. INT_PTR
  71. LaunchSetPasswordDlg(
  72. HWND hWnd,
  73. AccountInfo * pAccountInfo);
  74. INT_PTR APIENTRY
  75. SetPasswordDlgProc(
  76. HWND hDlg,
  77. UINT uMsg,
  78. WPARAM wParam,
  79. LPARAM lParam);
  80. INT_PTR APIENTRY
  81. SetAccountInformationDlgProc(
  82. HWND hDlg,
  83. UINT uMsg,
  84. WPARAM wParam,
  85. LPARAM lParam);
  86. #endif // !defined(_CHICAGO_)
  87. int
  88. SchedGetDlgItemTextLength(
  89. HWND hwnd,
  90. int id);
  91. //
  92. // (Control id, help id) list for context sensitivity help.
  93. //
  94. ULONG s_aGeneralPageHelpIds[] =
  95. {
  96. idc_icon, Hidc_icon,
  97. lbl_job_name, Hlbl_job_name,
  98. lbl_comments, Hlbl_comments,
  99. txt_comments, Htxt_comments,
  100. lbl_app_name, Hlbl_app_name,
  101. txt_app_name, Htxt_app_name,
  102. btn_browse, Hbtn_browse,
  103. lbl_workingdir, Hlbl_workingdir,
  104. txt_workingdir, Htxt_workingdir,
  105. lbl_run_as, Hlbl_execute_as,
  106. txt_run_as, Htxt_execute_as,
  107. btn_passwd, Hbtn_passwd,
  108. chk_enable_job, Hchk_enable_job,
  109. btn_settings, Hbtn_settings,
  110. 0,0
  111. };
  112. const ULONG s_aSetPasswordDlgHelpIds[] =
  113. {
  114. set_passwd_dlg, Hset_passwd_dlg,
  115. lbl_sp_passwd, Hlbl_sp_passwd,
  116. edt_sp_passwd, Hedt_sp_passwd,
  117. lbl_sp_cfrmpasswd, Hlbl_sp_cfrmpasswd,
  118. edt_sp_cfrmpasswd, Hedt_sp_cfrmpasswd,
  119. 0,0
  120. };
  121. extern "C" TCHAR szMstaskHelp[];
  122. const TCHAR SAGERUN_PARAM[] = TEXT("/SAGERUN:");
  123. TCHAR szMstaskHelp[] = TEXT("%windir%\\help\\mstask.hlp");
  124. //____________________________________________________________________________
  125. //____________________________________________________________________________
  126. //________________ ______________________________________
  127. //________________ class CGeneralPage ______________________________________
  128. //________________ ______________________________________
  129. //____________________________________________________________________________
  130. //____________________________________________________________________________
  131. class CGeneralPage : public CPropPage
  132. {
  133. public:
  134. CGeneralPage(ITask * pIJob, LPTSTR ptszTaskPath, BOOL fPersistChanges);
  135. ~CGeneralPage();
  136. private:
  137. virtual LRESULT _OnInitDialog(LPARAM lParam);
  138. virtual LRESULT _OnCommand(int id, HWND hwndCtl, UINT codeNotify);
  139. virtual LRESULT _OnApply(void);
  140. virtual LRESULT _OnCancel(void);
  141. virtual LRESULT _OnPSMQuerySibling(WPARAM wParam, LPARAM lParam);
  142. virtual LRESULT _OnPSNKillActive(LPARAM lParam);
  143. virtual LRESULT _OnHelp(HANDLE hRequesting, UINT uiHelpCommand);
  144. VOID _ExpandAppName(LPTSTR tszApp);
  145. VOID _ExpandWorkingDir();
  146. VOID _GetAppAndArgs(LPTSTR tszApp, LPTSTR * pptszArg);
  147. VOID _UpdateAppNameAndIcon(LPWSTR wszApp, LPWSTR * ppwszArg);
  148. VOID _UpdateAppIcon(LPCTSTR tszApp);
  149. VOID _SetAppEdit(LPCTSTR tszApp, LPCTSTR tszArgs);
  150. BOOL _JobObjectIsLocal();
  151. #if !defined(_CHICAGO_)
  152. void _UpdateRunAsControl(void);
  153. #endif // !defined(_CHICAGO_)
  154. BOOL _Browse(TCHAR szFilePath[]);
  155. void _ErrorDialog(int idsErr, LONG error = 0, UINT idsHelpHint = 0)
  156. { SchedUIErrorDialog(Hwnd(), idsErr, error, idsHelpHint); }
  157. #if !defined(_CHICAGO_)
  158. AccountInfo m_AccountInfo; // Account/password change info.
  159. #endif // !defined(_CHICAGO_)
  160. ITask * m_pIJob;
  161. // Flag values. Note the compiler allocates a single dword for these
  162. DWORD m_CommentDirty : 1; //
  163. DWORD m_AppNameDirty : 1; //
  164. DWORD m_WorkingDirDirty : 1; // A value of 1 => dirty
  165. DWORD m_RunAsDirty : 1; //
  166. DWORD m_updateIcon : 1; // 1 => update needed
  167. DWORD m_ChangeFromSetText : 1;// 0 => en_change from user
  168. //
  169. // icon helper
  170. //
  171. CIconHelper * m_pIconHelper;
  172. //
  173. // Should we save on Apply or OK.
  174. //
  175. BOOL m_fPersistChanges;
  176. BOOL m_fEnableJob;
  177. //
  178. // Saved or new sage settings parameter
  179. //
  180. TCHAR m_tszSageRunParam[20]; // /SAGERUN:4294967295
  181. #if !defined(_CHICAGO_)
  182. //
  183. // The RunAs edit control can be updated by the user, or automatically
  184. // with apply via the set account information dialog. In response to
  185. // user edits, we want to apply the changes. For the automatic RunAs
  186. // update, we've already applied the changes, therefore, this flag
  187. // exists to not re-dirty the page.
  188. //
  189. BOOL m_fApplyRunAsEditChange;
  190. //
  191. // The other pages need to query the general page if there is an
  192. // application or security account change for the common security
  193. // code in the page's save path (JFSaveJob). The record of this
  194. // dirty information must be retained post-Apply; therefore, these
  195. // slightly redundant flags are necessary.
  196. //
  197. BOOL m_fTaskApplicationChange;
  198. BOOL m_fTaskAccountChange;
  199. //
  200. // Set this flag to TRUE if we have launched the set password dialog.
  201. // Othwerwise, the user may get a redundant set account information
  202. // dialog on apply.
  203. //
  204. BOOL m_fSuppressAcctInfoRequestOnApply;
  205. #endif // !defined(_CHICAGO_)
  206. }; // class CGeneralPage
  207. inline
  208. CGeneralPage::CGeneralPage(
  209. ITask * pIJob,
  210. LPTSTR ptszTaskPath,
  211. BOOL fPersistChanges)
  212. :
  213. m_pIJob(pIJob),
  214. m_pIconHelper(NULL),
  215. m_fPersistChanges(fPersistChanges),
  216. m_ChangeFromSetText(FALSE),
  217. #if !defined(_CHICAGO_)
  218. m_fApplyRunAsEditChange(TRUE),
  219. m_fTaskApplicationChange(FALSE),
  220. m_fTaskAccountChange(FALSE),
  221. m_fSuppressAcctInfoRequestOnApply(FALSE),
  222. #endif // !defined(_CHICAGO_)
  223. CPropPage(MAKEINTRESOURCE(general_page), ptszTaskPath)
  224. {
  225. TRACE(CGeneralPage, CGeneralPage);
  226. Win4Assert(m_pIJob != NULL);
  227. m_pIJob->AddRef();
  228. m_tszSageRunParam[0] = TEXT('\0');
  229. #if !defined(_CHICAGO_)
  230. InitializeAccountInfo(&m_AccountInfo);
  231. #endif // !defined(_CHICAGO_)
  232. }
  233. inline
  234. CGeneralPage::~CGeneralPage()
  235. {
  236. TRACE(CGeneralPage, ~CGeneralPage);
  237. if (m_pIconHelper != NULL)
  238. {
  239. m_pIconHelper->Release();
  240. }
  241. if (m_pIJob != NULL)
  242. {
  243. m_pIJob->Release();
  244. }
  245. #if !defined(_CHICAGO_)
  246. ResetAccountInfo(&m_AccountInfo);
  247. #endif // !defined(_CHICAGO_)
  248. }
  249. //+--------------------------------------------------------------------------
  250. //
  251. // Member: CGeneralPage::_JobObjectIsLocal
  252. //
  253. // Synopsis: Return TRUE if job object being edited lives on the local
  254. // machine, FALSE otherwise.
  255. //
  256. // History: 2-01-1997 DavidMun Created
  257. //
  258. //---------------------------------------------------------------------------
  259. inline BOOL
  260. CGeneralPage::_JobObjectIsLocal()
  261. {
  262. return IsLocalFilename(GetTaskPath());
  263. }
  264. LRESULT
  265. CGeneralPage::_OnInitDialog(
  266. LPARAM lParam)
  267. {
  268. TRACE(CGeneralPage, _OnInitDialog);
  269. HRESULT hr = S_OK;
  270. LPWSTR pwsz = NULL;
  271. BOOL fEnableSecurity = FALSE;
  272. TCHAR tszApp[MAX_PATH + 1] = TEXT("");
  273. //
  274. // Note that we don't limit the txt_app_name control. App names are
  275. // limited to MAX_PATH characters, but app parameters are not.
  276. //
  277. Edit_LimitText(_hCtrl(txt_comments), MAX_PATH);
  278. Edit_LimitText(_hCtrl(txt_workingdir), MAX_PATH);
  279. Edit_LimitText(_hCtrl(txt_run_as), MAX_USERNAME);
  280. //
  281. // Policy - if this reg key is valid, disable browse
  282. //
  283. if (RegReadPolicyKey(TS_KEYPOLICY_DENY_BROWSE))
  284. {
  285. DEBUG_OUT((DEB_ITRACE, "Policy ALLOW_BROWSE active, no browse or edit\n"));
  286. EnableWindow(_hCtrl(btn_browse), FALSE);
  287. ShowWindow(_hCtrl(btn_browse), SW_HIDE);
  288. EnableWindow(_hCtrl(txt_app_name), FALSE);
  289. EnableWindow(_hCtrl(txt_workingdir), FALSE);
  290. }
  291. do
  292. {
  293. #if !defined(_CHICAGO_)
  294. //
  295. // NB : For the first release of the scheduling agent, all security
  296. // operations are disabled under Win95, even Win95 to NT.
  297. //
  298. //
  299. // Determine if the security settings should be shown or not.
  300. // The task object must reside within a tasks folder & exist
  301. // on an NT machine.
  302. //
  303. fEnableSecurity = (this->GetPlatformId() == VER_PLATFORM_WIN32_NT &&
  304. this->IsTaskInTasksFolder());
  305. #else
  306. fEnableSecurity = FALSE;
  307. #endif // !defined(_CHICAGO_)
  308. if (!fEnableSecurity)
  309. {
  310. DestroyWindow(_hCtrl(lbl_run_as));
  311. DestroyWindow(_hCtrl(txt_run_as));
  312. DestroyWindow(_hCtrl(btn_passwd));
  313. }
  314. // See if the schedule page has already created the icon
  315. // helper, if not create it here.
  316. m_pIconHelper = (CIconHelper *)PropSheet_QuerySiblings(
  317. GetParent(Hwnd()), GET_ICON_HELPER, 0);
  318. if (m_pIconHelper == NULL)
  319. {
  320. m_pIconHelper = new CIconHelper();
  321. if (m_pIconHelper == NULL)
  322. {
  323. hr = E_OUTOFMEMORY;
  324. break;
  325. }
  326. }
  327. else
  328. {
  329. m_pIconHelper->AddRef();
  330. }
  331. //
  332. // Set job name (static text showing path to .job object)
  333. //
  334. SetDlgItemText(Hwnd(), lbl_job_name, this->GetTaskPath());
  335. //
  336. // Set comments
  337. //
  338. hr = m_pIJob->GetComment(&pwsz);
  339. CHECK_HRESULT(hr);
  340. BREAK_ON_FAIL(hr);
  341. I_SetDlgItemText(Hwnd(), txt_comments, pwsz);
  342. CoTaskMemFree(pwsz);
  343. //
  344. // Get application name preparatory to setting it.
  345. //
  346. hr = m_pIJob->GetApplicationName(&pwsz);
  347. CHECK_HRESULT(hr);
  348. BREAK_ON_FAIL(hr);
  349. #if defined(_CHICAGO_)
  350. //
  351. // Show the settings button only on Win95 and only if the task's
  352. // application is Sage-aware. Using the ApplicationName property in
  353. // pwsz, before it is freed below.
  354. //
  355. hr = UnicodeToAnsi(tszApp, pwsz, MAX_PATH+1);
  356. if (SUCCEEDED(hr) && !IsSageAware(tszApp, NULL, NULL))
  357. {
  358. //
  359. // The app isn't Sage-aware, so hide the Settings button and
  360. // move the Browse button to the Settings button position.
  361. //
  362. HWND hBrowseBtn = GetDlgItem(Hwnd(), btn_browse);
  363. HWND hSettingsBtn = GetDlgItem(Hwnd(), btn_settings);
  364. WINDOWPLACEMENT wp;
  365. wp.length = sizeof(WINDOWPLACEMENT);
  366. GetWindowPlacement(hSettingsBtn, &wp);
  367. ShowWindow(hSettingsBtn, SW_HIDE);
  368. MoveWindow(hBrowseBtn,
  369. wp.rcNormalPosition.left,
  370. wp.rcNormalPosition.top,
  371. wp.rcNormalPosition.right - wp.rcNormalPosition.left,
  372. wp.rcNormalPosition.bottom - wp.rcNormalPosition.top,
  373. FALSE);
  374. }
  375. #else
  376. lstrcpyn(tszApp, pwsz, MAX_PATH + 1);
  377. #endif // defined(_CHICAGO_)
  378. //
  379. // If the application name fetched from the job object has spaces in
  380. // it, add quotes around the tchar version.
  381. //
  382. if (wcschr(pwsz, L' '))
  383. {
  384. AddQuotes(tszApp, MAX_PATH + 1);
  385. }
  386. CoTaskMemFree(pwsz);
  387. //
  388. // Now get the parameters and append a space and the tchar
  389. // representation to the app name.
  390. //
  391. hr = m_pIJob->GetParameters(&pwsz);
  392. CHECK_HRESULT(hr);
  393. BREAK_ON_FAIL(hr);
  394. #if !defined(UNICODE)
  395. TCHAR tszArg[MAX_PATH + 1];
  396. UnicodeToAnsi(tszArg, pwsz, MAX_PATH + 1);
  397. #else
  398. TCHAR * tszArg = pwsz;
  399. #endif // !defined(UNICODE)
  400. //
  401. // If the /SAGERUN:n parameter appears in the arguments, save it in
  402. // an internal buffer, but don't show it in the UI.
  403. //
  404. LPTSTR ptszSageRun = _tcsstr(tszArg, SAGERUN_PARAM);
  405. if (ptszSageRun)
  406. {
  407. lstrcpyn(m_tszSageRunParam,
  408. ptszSageRun,
  409. ARRAYLEN(m_tszSageRunParam));
  410. *ptszSageRun = TEXT('\0');
  411. StripLeadTrailSpace(tszArg); // get rid of spaces before /sagerun
  412. }
  413. _SetAppEdit(tszApp, tszArg);
  414. CoTaskMemFree(pwsz);
  415. //
  416. // Set the working directory
  417. //
  418. hr = m_pIJob->GetWorkingDirectory(&pwsz);
  419. CHECK_HRESULT(hr);
  420. BREAK_ON_FAIL(hr);
  421. if (wcschr(pwsz, L' '))
  422. {
  423. WCHAR wszWorkingDir[MAX_PATH + 1] = L"\"";
  424. wcsncpy(wszWorkingDir + 1, pwsz, MAX_PATH - 1);
  425. wcscat(wszWorkingDir, L"\"");
  426. I_SetDlgItemText(Hwnd(), txt_workingdir, wszWorkingDir);
  427. }
  428. else
  429. {
  430. I_SetDlgItemText(Hwnd(), txt_workingdir, pwsz);
  431. }
  432. CoTaskMemFree(pwsz);
  433. //
  434. // Set the job enabled check box
  435. //
  436. DWORD dwFlags;
  437. hr = m_pIJob->GetFlags(&dwFlags);
  438. m_fEnableJob = (dwFlags & TASK_FLAG_DISABLED) ? FALSE : TRUE;
  439. CheckDlgButton(m_hPage, chk_enable_job, m_fEnableJob);
  440. if (!this->IsTaskInTasksFolder())
  441. {
  442. EnableWindow(_hCtrl(chk_enable_job), FALSE);
  443. m_fEnableJob = FALSE;
  444. }
  445. #if !defined(_CHICAGO_)
  446. if (fEnableSecurity)
  447. {
  448. //
  449. // Set account name (run as)
  450. //
  451. hr = m_pIJob->GetAccountInformation(&pwsz);
  452. if (SUCCEEDED(hr))
  453. {
  454. I_SetDlgItemText(Hwnd(), txt_run_as, pwsz);
  455. m_AccountInfo.pwszAccountName = pwsz;
  456. EnableWindow(_hCtrl(btn_passwd), TRUE);
  457. }
  458. else if (hr == SCHED_E_ACCOUNT_INFORMATION_NOT_SET)
  459. {
  460. hr = S_OK;
  461. //
  462. // Set the run as field to the current user's name and
  463. // enable the set/change password button.
  464. // Leave it blank for AT jobs - else they look like they've
  465. // been set to run as this user, which is very confusing
  466. // (see bug 376163). BUGBUG Better behavior would be to
  467. // display a status message that this is an AT job and will
  468. // be upgraded if modified.
  469. //
  470. TCHAR tszUserName[MAX_USERNAME + 1] = TEXT("");
  471. if (! (dwFlags & JOB_I_FLAG_NET_SCHEDULE))
  472. {
  473. GetDefaultDomainAndUserName(tszUserName, MAX_USERNAME + 1);
  474. }
  475. SetDlgItemText(Hwnd(), txt_run_as, tszUserName);
  476. EnableWindow(_hCtrl(btn_passwd), TRUE);
  477. }
  478. else
  479. {
  480. //
  481. // Disable the run as and set/change password button ctrls &
  482. // put up an error dialog letting the user know that security
  483. // services are unavailable.
  484. //
  485. // Actually, the set/change password button is already
  486. // disabled.
  487. //
  488. CHECK_HRESULT(hr);
  489. EnableWindow(_hCtrl(lbl_run_as), FALSE);
  490. EnableWindow(_hCtrl(txt_run_as), FALSE);
  491. }
  492. }
  493. #endif // !defined(_CHICAGO_)
  494. } while (0);
  495. if (FAILED(hr))
  496. {
  497. if (hr == E_OUTOFMEMORY)
  498. {
  499. _ErrorDialog(IERR_OUT_OF_MEMORY);
  500. }
  501. else
  502. {
  503. _ErrorDialog(IERR_GENERAL_PAGE_INIT, hr);
  504. }
  505. //
  506. // Show application icon
  507. //
  508. m_updateIcon = 1;
  509. _UpdateAppIcon(tszApp);
  510. EnableWindow(Hwnd(), FALSE);
  511. return FALSE;
  512. }
  513. //
  514. // Show application icon
  515. //
  516. m_updateIcon = 1;
  517. _UpdateAppIcon(tszApp);
  518. //
  519. // Need to initialize these here since doing a SetDlgItemText causes
  520. // a WM_COMMAND msg with EN_CHANGE to be called for edit boxes.
  521. //
  522. m_CommentDirty = 0;
  523. m_AppNameDirty = 0;
  524. m_WorkingDirDirty = 0;
  525. m_RunAsDirty = 0;
  526. m_fDirty = FALSE;
  527. return TRUE;
  528. }
  529. #if !defined(_CHICAGO_)
  530. //+--------------------------------------------------------------------------
  531. //
  532. // Function: GetDefaultDomainAndUserName
  533. //
  534. // Synopsis: Fill [ptszDomainAndUserName] with "domain\user" string
  535. //
  536. // Arguments: [ptszDomainAndUserName] - buffer to receive string
  537. // [cchBuf] - should be at least MAX_USERNAME
  538. //
  539. // Modifies: *[ptszDomainAndUserName].
  540. //
  541. // History: 06-03-1997 DavidMun Created
  542. //
  543. // Notes: If an error occurs while retrieving the domain name, only
  544. // the user name is returned. If even that cannot be
  545. // retrieved, the buffer is set to an empty string.
  546. //
  547. //---------------------------------------------------------------------------
  548. VOID
  549. GetDefaultDomainAndUserName(
  550. LPTSTR ptszDomainAndUserName,
  551. ULONG cchBuf)
  552. {
  553. TRACE_FUNCTION(GetDefaultDomainAndUserName);
  554. if (!GetUserNameEx(NameSamCompatible,
  555. ptszDomainAndUserName,
  556. &cchBuf))
  557. {
  558. DEBUG_OUT((DEB_ERROR,
  559. "GetDefaultDomainAndUserName: GetUserNameEx failed %d\n",
  560. GetLastError()));
  561. ptszDomainAndUserName[0] = L'\0';
  562. }
  563. }
  564. #endif // !defined(_CHICAGO_)
  565. void
  566. CGeneralPage::_UpdateAppIcon(
  567. LPCTSTR ptszAppName)
  568. {
  569. if (m_updateIcon == 0)
  570. {
  571. return;
  572. }
  573. m_updateIcon = 0;
  574. if (ptszAppName)
  575. {
  576. m_pIconHelper->SetAppIcon((LPTSTR)ptszAppName);
  577. }
  578. BOOL fEnabled;
  579. if (this->IsTaskInTasksFolder())
  580. {
  581. fEnabled = (IsDlgButtonChecked(m_hPage, chk_enable_job)
  582. == BST_CHECKED);
  583. }
  584. else
  585. {
  586. fEnabled = FALSE;
  587. }
  588. m_pIconHelper->SetJobIcon(fEnabled);
  589. SendDlgItemMessage(Hwnd(), idc_icon, STM_SETICON,
  590. (WPARAM)m_pIconHelper->hiconJob, 0L);
  591. }
  592. BOOL
  593. CGeneralPage::_Browse(
  594. TCHAR szFilePath[]) // of size MAX_PATH
  595. {
  596. TCHAR szDefExt[5];
  597. TCHAR szBrowserDir[MAX_PATH];
  598. TCHAR szFilters[MAX_PATH];
  599. TCHAR szTitle[100];
  600. DWORD dwFlags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
  601. LoadString(g_hInstance, IDS_EXE, szDefExt, ARRAYLEN(szDefExt));
  602. LoadString(g_hInstance, IDS_BROWSE, szTitle, ARRAYLEN(szTitle));
  603. ZeroMemory(szFilters, ARRAYLEN(szFilters));
  604. if (!LoadString(g_hInstance,
  605. IDS_PROGRAMSFILTER,
  606. szFilters,
  607. ARRAYLEN(szFilters)))
  608. {
  609. CHECK_HRESULT( HRESULT_FROM_WIN32(GetLastError()) );
  610. return FALSE;
  611. }
  612. GetCurrentDirectory(MAX_PATH, szBrowserDir);
  613. OPENFILENAME ofn;
  614. ZeroMemory(&ofn, sizeof(ofn));
  615. szFilePath[0] = TEXT('\0');
  616. // Setup info for comm dialog.
  617. ofn.lStructSize = CDSIZEOF_STRUCT(OPENFILENAME, lpTemplateName);
  618. ofn.hwndOwner = Hwnd();
  619. ofn.hInstance = g_hInstance;
  620. ofn.lpstrFilter = szFilters;
  621. ofn.nFilterIndex = 1;
  622. ofn.lpstrFile = szFilePath;
  623. ofn.nMaxFile = MAX_PATH;
  624. ofn.lpstrInitialDir = szBrowserDir;
  625. ofn.lpstrTitle = szTitle;
  626. ofn.Flags = dwFlags;
  627. ofn.lpstrDefExt = szDefExt;
  628. // Call it.
  629. if (GetOpenFileName(&ofn) == FALSE)
  630. {
  631. DEBUG_OUT((DEB_ERROR, "GetOpenFileName failed<0x%x>\n",
  632. CommDlgExtendedError()));
  633. return FALSE;
  634. }
  635. return TRUE;
  636. }
  637. LRESULT
  638. CGeneralPage::_OnCommand(
  639. int id,
  640. HWND hwndCtl,
  641. UINT codeNotify)
  642. {
  643. TRACE(CGeneralPage, _OnCommand);
  644. if ((id == btn_browse) && (codeNotify == BN_CLICKED))
  645. {
  646. // popup the file browse dialog
  647. TCHAR tszFilePath[MAX_PATH+1];
  648. if (_Browse(tszFilePath))
  649. {
  650. if (_tcschr(tszFilePath, TEXT(' ')))
  651. {
  652. AddQuotes(tszFilePath, MAX_PATH);
  653. }
  654. SetDlgItemText(Hwnd(), txt_app_name, tszFilePath);
  655. SendMessage(Hwnd(),
  656. WM_NEXTDLGCTL,
  657. (WPARAM)_hCtrl(txt_workingdir),
  658. TRUE);
  659. _UpdateAppIcon(tszFilePath);
  660. _EnableApplyButton();
  661. }
  662. }
  663. #if defined(_CHICAGO_)
  664. else if (id == btn_settings && codeNotify == BN_CLICKED)
  665. {
  666. TCHAR tszApp[MAX_PATH + 1];
  667. _GetAppAndArgs(tszApp, NULL);
  668. // invoke the application to do its settings.
  669. BOOL fHadSageRun = (*m_tszSageRunParam != '\0');
  670. DoSageSettings(tszApp, m_tszSageRunParam);
  671. //
  672. // If the DoSageSettings func created a /sagerun parameter,
  673. // mark the app name as dirty, since the sagerun parameter doesn't
  674. // appear in the UI, therefore we won't be doing a settext with
  675. // it and automatically dirtying.
  676. //
  677. if (!fHadSageRun && *m_tszSageRunParam)
  678. {
  679. m_AppNameDirty = 1;
  680. _EnableApplyButton();
  681. }
  682. }
  683. #endif // defined(_CHICAGO_)
  684. #if !defined(_CHICAGO_)
  685. else if (id == btn_passwd && codeNotify == BN_CLICKED)
  686. {
  687. // popup the set password dialog
  688. LaunchSetPasswordDlg(Hwnd(), &m_AccountInfo);
  689. //
  690. // Since we've launched the set password dialog, we want
  691. // to suppress the set account information dialog which
  692. // otherwise may come up on apply.
  693. //
  694. m_fSuppressAcctInfoRequestOnApply = TRUE;
  695. _EnableApplyButton();
  696. }
  697. #endif // !defined(_CHICAGO_)
  698. else if (codeNotify == EN_CHANGE)
  699. {
  700. switch (id)
  701. {
  702. case txt_comments:
  703. m_CommentDirty = 1;
  704. break;
  705. case txt_app_name:
  706. //
  707. // If we just did a SetDlgItemText, then this change notification
  708. // should be ignored.
  709. //
  710. if (m_ChangeFromSetText)
  711. {
  712. m_ChangeFromSetText = 0;
  713. }
  714. else
  715. {
  716. m_AppNameDirty = 1;
  717. m_updateIcon = 1;
  718. }
  719. break;
  720. case txt_workingdir:
  721. m_WorkingDirDirty = 1;
  722. break;
  723. case txt_run_as:
  724. #if !defined(_CHICAGO_)
  725. //
  726. // If m_fApplyRunAsEditChange is TRUE, the user has edited
  727. // the RunAs control, therefore, we want to apply changes.
  728. // If FALSE, the RunAs control has been automatically updated
  729. // by the UI as a result of an apply. In this case, we do
  730. // not want to apply the change, as it already has been.
  731. //
  732. if (m_fApplyRunAsEditChange)
  733. {
  734. m_RunAsDirty = 1;
  735. EnableWindow(_hCtrl(btn_passwd), TRUE);
  736. break;
  737. }
  738. else
  739. {
  740. Win4Assert(!m_fDirty);
  741. return TRUE;
  742. }
  743. #endif // !defined(_CHICAGO_)
  744. default:
  745. return FALSE;
  746. }
  747. _EnableApplyButton();
  748. }
  749. else if (codeNotify == EN_KILLFOCUS &&
  750. id == txt_app_name)
  751. {
  752. if (m_AppNameDirty == 1)
  753. {
  754. TCHAR tszApp[MAX_PATH + 1];
  755. _GetAppAndArgs(tszApp, NULL);
  756. if (_JobObjectIsLocal())
  757. {
  758. _ExpandAppName(tszApp);
  759. }
  760. _UpdateAppIcon(tszApp);
  761. }
  762. }
  763. else if (id == chk_enable_job)
  764. {
  765. _EnableApplyButton();
  766. m_updateIcon = 1;
  767. _UpdateAppIcon(NULL);
  768. }
  769. return TRUE;
  770. }
  771. LRESULT
  772. CGeneralPage::_OnApply(void)
  773. {
  774. TRACE(CGeneralPage, _OnApply);
  775. //DbxDisplay("CGeneralPage::_OnApply");
  776. if (m_fDirty == FALSE)
  777. {
  778. return TRUE;
  779. }
  780. HRESULT hr = S_OK;
  781. WCHAR wcBuff[MAX_PATH+1];
  782. LPWSTR pwszArg = NULL;
  783. do
  784. {
  785. if (m_CommentDirty == 1)
  786. {
  787. wcBuff[0] = L'\0';
  788. I_GetDlgItemText(Hwnd(), txt_comments, wcBuff, MAX_PATH+1);
  789. hr = m_pIJob->SetComment(wcBuff);
  790. CHECK_HRESULT(hr);
  791. BREAK_ON_FAIL(hr);
  792. m_CommentDirty = 0;
  793. }
  794. #if !defined(_CHICAGO_)
  795. m_fTaskApplicationChange = FALSE;
  796. #endif // !defined(_CHICAGO_)
  797. if (m_AppNameDirty == 1)
  798. {
  799. WCHAR wszApp[MAX_PATH + 1];
  800. _UpdateAppNameAndIcon(wszApp, &pwszArg);
  801. if (pwszArg == NULL)
  802. {
  803. break;
  804. }
  805. hr = m_pIJob->SetApplicationName(wszApp);
  806. CHECK_HRESULT(hr);
  807. BREAK_ON_FAIL(hr);
  808. //
  809. // Since the application name has changed, it may no longer name
  810. // (or may now name) a sage-aware application. Make sure that
  811. // the sagerun argument is appended only if it should be.
  812. //
  813. // BUGBUG IsSageAware and CreateSageRunKey use HKLM, so they're
  814. // broken for remote case. If this is fixed, enable this code
  815. // on NT if the target machine is win9x.
  816. //
  817. // BUGBUG pwszArg is limited to MAX_PATH characters on Win9x.
  818. //
  819. #if defined(_CHICAGO_)
  820. int iSageRun;
  821. if (IsSageAwareW(wszApp, pwszArg, &iSageRun))
  822. {
  823. wsprintf(m_tszSageRunParam,
  824. TEXT("%s%u"),
  825. SAGERUN_PARAM,
  826. iSageRun);
  827. CHAR szApp[MAX_PATH + 1];
  828. UnicodeToAnsi(szApp, wszApp, ARRAYLEN(szApp));
  829. LPSTR pszFileName = PathFindFileName(szApp);
  830. if (pszFileName)
  831. {
  832. CreateSageRunKey(pszFileName, iSageRun);
  833. }
  834. }
  835. else
  836. {
  837. *m_tszSageRunParam = TEXT('\0');
  838. }
  839. WCHAR wszArg[MAX_PATH + 1];
  840. ULONG cchArg = wcslen(pwszArg);
  841. if (*m_tszSageRunParam &&
  842. lstrlen(m_tszSageRunParam) + cchArg + 1 < ARRAYLEN(wszArg))
  843. {
  844. wcscpy(wszArg, pwszArg);
  845. if (cchArg)
  846. {
  847. wszArg[cchArg++] = L' ';
  848. }
  849. AnsiToUnicode(&wszArg[cchArg],
  850. m_tszSageRunParam,
  851. ARRAYLEN(wszArg) - cchArg);
  852. hr = m_pIJob->SetParameters(wszArg);
  853. }
  854. else
  855. {
  856. hr = m_pIJob->SetParameters(pwszArg);
  857. }
  858. #else
  859. hr = m_pIJob->SetParameters(pwszArg);
  860. #endif // defined(_CHICAGO_)
  861. CHECK_HRESULT(hr);
  862. BREAK_ON_FAIL(hr);
  863. m_AppNameDirty = 0;
  864. #if !defined(_CHICAGO_)
  865. m_fTaskApplicationChange = TRUE;
  866. #endif // !defined(_CHICAGO_)
  867. }
  868. if (m_WorkingDirDirty == 1)
  869. {
  870. wcBuff[0] = L'\0';
  871. _ExpandWorkingDir();
  872. I_GetDlgItemText(Hwnd(), txt_workingdir, wcBuff, MAX_PATH+1);
  873. hr = m_pIJob->SetWorkingDirectory(wcBuff);
  874. CHECK_HRESULT(hr);
  875. BREAK_ON_FAIL(hr);
  876. m_WorkingDirDirty = 0;
  877. }
  878. //
  879. // For the first release of the scheduling agent, all security
  880. // operations are disabled under Win95, even Win95 to NT.
  881. //
  882. #if !defined(_CHICAGO_)
  883. m_fTaskAccountChange = FALSE;
  884. if (m_RunAsDirty == 1 || m_AccountInfo.pwszPassword != tszEmpty)
  885. {
  886. wcBuff[0] = L'\0';
  887. DWORD ccAccountName = I_GetDlgItemText(Hwnd(),
  888. txt_run_as,
  889. wcBuff,
  890. MAX_USERNAME + 1);
  891. if ((m_RunAsDirty == 1 && m_AccountInfo.pwszAccountName == NULL) ||
  892. (m_RunAsDirty == 1 && m_AccountInfo.pwszAccountName != NULL &&
  893. lstrcmpiW(m_AccountInfo.pwszAccountName, wcBuff) != 0))
  894. {
  895. //
  896. // The user has changed the account name. Check if they have
  897. // specified a password.
  898. //
  899. if (m_AccountInfo.pwszPassword == tszEmpty)
  900. {
  901. //
  902. // User hasn't specified a password. Launch the set
  903. // password dialog.
  904. //
  905. LaunchSetPasswordDlg(Hwnd(), &m_AccountInfo);
  906. //
  907. // Since we've launched the set password dialog, we want
  908. // to suppress the set account information dialog which
  909. // otherwise may come up on apply.
  910. //
  911. m_fSuppressAcctInfoRequestOnApply = TRUE;
  912. }
  913. }
  914. if (m_AccountInfo.pwszPassword != tszEmpty)
  915. {
  916. hr = m_pIJob->SetAccountInformation(
  917. wcBuff,
  918. m_AccountInfo.pwszPassword);
  919. if (FAILED(hr))
  920. {
  921. CHECK_HRESULT(hr);
  922. break;
  923. }
  924. m_RunAsDirty = 0;
  925. m_AccountInfo.fDirty = FALSE;
  926. m_fTaskAccountChange = TRUE;
  927. }
  928. }
  929. #endif // !defined(_CHICAGO_)
  930. //
  931. // Save the job enabled state
  932. //
  933. if (this->IsTaskInTasksFolder())
  934. {
  935. DWORD dwFlags;
  936. hr = m_pIJob->GetFlags(&dwFlags);
  937. BOOL fTemp = (IsDlgButtonChecked(m_hPage, chk_enable_job)
  938. == BST_CHECKED);
  939. if (m_fEnableJob != fTemp)
  940. {
  941. m_fEnableJob = fTemp;
  942. if (m_fEnableJob == TRUE)
  943. {
  944. dwFlags &= ~TASK_FLAG_DISABLED;
  945. }
  946. else
  947. {
  948. dwFlags |= TASK_FLAG_DISABLED;
  949. }
  950. hr = m_pIJob->SetFlags(dwFlags);
  951. CHECK_HRESULT(hr);
  952. BREAK_ON_FAIL(hr);
  953. }
  954. }
  955. //
  956. // reset dirty flag
  957. //
  958. m_fDirty = FALSE;
  959. //
  960. // If evrything went well see if the other pages are ready to
  961. // save the job to storage.
  962. //
  963. if ((m_fPersistChanges == TRUE) &&
  964. (PropSheet_QuerySiblings(GetParent(Hwnd()),
  965. QUERY_READY_TO_BE_SAVED, 0))
  966. == 0)
  967. {
  968. //
  969. // Save the job file to storage.
  970. //
  971. // For the first release of the scheduling agent, all security
  972. // operations are disabled under Win95, even Win95 to NT.
  973. //
  974. hr = JFSaveJob(Hwnd(),
  975. m_pIJob,
  976. #if !defined(_CHICAGO_)
  977. this->GetPlatformId() == VER_PLATFORM_WIN32_NT &&
  978. this->IsTaskInTasksFolder(),
  979. m_fTaskAccountChange,
  980. m_fTaskApplicationChange,
  981. m_fSuppressAcctInfoRequestOnApply);
  982. #else
  983. FALSE,
  984. FALSE,
  985. FALSE,
  986. TRUE);
  987. #endif // !defined(_CHICAGO_)
  988. CHECK_HRESULT(hr);
  989. BREAK_ON_FAIL(hr);
  990. #if !defined(_CHICAGO_)
  991. m_fTaskApplicationChange = FALSE;
  992. m_fTaskAccountChange = FALSE;
  993. m_fSuppressAcctInfoRequestOnApply = FALSE;
  994. // Will result in refresh of the run as edit control.
  995. //
  996. _UpdateRunAsControl();
  997. #endif // !defined(_CHICAGO_)
  998. }
  999. } while (0);
  1000. delete [] pwszArg;
  1001. if (FAILED(hr))
  1002. {
  1003. if (hr == E_OUTOFMEMORY)
  1004. {
  1005. _ErrorDialog(IERR_OUT_OF_MEMORY);
  1006. }
  1007. else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
  1008. {
  1009. _ErrorDialog(IERR_FILE_NOT_FOUND);
  1010. }
  1011. else if (hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED))
  1012. {
  1013. _ErrorDialog(IERR_ACCESS_DENIED);
  1014. }
  1015. else
  1016. {
  1017. _ErrorDialog(IERR_INTERNAL_ERROR, hr);
  1018. }
  1019. }
  1020. return SUCCEEDED(hr);
  1021. }
  1022. //+--------------------------------------------------------------------------
  1023. //
  1024. // Member: CGeneralPage::_UpdateAppNameAndIcon
  1025. //
  1026. // Synopsis: Update the application name edit control with an expanded
  1027. // path for the app, then update the icon for the new path.
  1028. //
  1029. // Arguments: [wszApp] - NULL or buffer to receive WCHAR app name
  1030. // [ppwszArgs] - NULL or address of pointer to buffer to receive
  1031. // WCHAR arguments. Must be deallocated with delete[].
  1032. //
  1033. // Modifies: *[wszApp], *[ppwszArgs]
  1034. //
  1035. // History: 1-31-1997 DavidMun Created
  1036. //
  1037. // Notes: App path is only expanded if job object is local.
  1038. //
  1039. //---------------------------------------------------------------------------
  1040. VOID
  1041. CGeneralPage::_UpdateAppNameAndIcon(
  1042. LPWSTR wszApp,
  1043. LPWSTR * ppwszArgs)
  1044. {
  1045. TCHAR tszApp[MAX_PATH + 1];
  1046. LPTSTR ptszArgs = NULL;
  1047. TCHAR tszAppAndArg[MAX_PATH + 1];
  1048. _GetAppAndArgs(tszApp, &ptszArgs);
  1049. if (ptszArgs == NULL)
  1050. {
  1051. return;
  1052. }
  1053. if (_JobObjectIsLocal())
  1054. {
  1055. _ExpandAppName(tszApp);
  1056. m_updateIcon = 1;
  1057. _UpdateAppIcon(tszApp);
  1058. //
  1059. // If the working directory is empty and the app is on the local
  1060. // machine, provide a default of the directory where the app lives.
  1061. //
  1062. TCHAR tszWorkingDir[MAX_PATH + 1];
  1063. GetDlgItemText(Hwnd(), txt_workingdir, tszWorkingDir, MAX_PATH + 1);
  1064. StripLeadTrailSpace(tszWorkingDir);
  1065. DeleteQuotes(tszWorkingDir);
  1066. if (!*tszWorkingDir && IsLocalFilename(tszApp))
  1067. {
  1068. lstrcpy(tszWorkingDir, tszApp);
  1069. DeleteQuotes(tszWorkingDir);
  1070. // Get rid of the filename at the end of the string
  1071. PathRemoveFileSpec(tszWorkingDir);
  1072. if (HasSpaces(tszWorkingDir))
  1073. {
  1074. AddQuotes(tszWorkingDir, MAX_PATH + 1);
  1075. }
  1076. SetDlgItemText(Hwnd(), txt_workingdir, tszWorkingDir);
  1077. }
  1078. m_ChangeFromSetText = 1;
  1079. _SetAppEdit(tszApp, ptszArgs);
  1080. }
  1081. if (wszApp)
  1082. {
  1083. #if !defined(UNICODE)
  1084. AnsiToUnicode(wszApp, tszApp, MAX_PATH + 1);
  1085. #else
  1086. lstrcpy(wszApp, tszApp);
  1087. #endif // defined(UNICODE)
  1088. }
  1089. if (ppwszArgs)
  1090. {
  1091. #if !defined(UNICODE)
  1092. LONG cch = lstrlen(ptszArgs) + 1;
  1093. *ppwszArgs = new WCHAR[cch];
  1094. if (*ppwszArgs != NULL)
  1095. {
  1096. AnsiToUnicode(*ppwszArgs, ptszArgs, cch);
  1097. }
  1098. delete [] ptszArgs;
  1099. #else
  1100. *ppwszArgs = ptszArgs;
  1101. #endif // defined(UNICODE)
  1102. }
  1103. else
  1104. {
  1105. delete [] ptszArgs;
  1106. }
  1107. }
  1108. //+--------------------------------------------------------------------------
  1109. //
  1110. // Member: CGeneralPage::_ExpandWorkingDir
  1111. //
  1112. // Synopsis: Replace the string in the working directory edit control
  1113. // with one which has expanded environment strings.
  1114. //
  1115. // History: 06-04-1997 DavidMun Created
  1116. //
  1117. // Notes: Note that this will result in the working dir being marked
  1118. // as dirty.
  1119. //
  1120. //---------------------------------------------------------------------------
  1121. VOID
  1122. CGeneralPage::_ExpandWorkingDir()
  1123. {
  1124. TCHAR tszApp[MAX_PATH + 1];
  1125. TCHAR tszAppAndArg[MAX_PATH + 1];
  1126. //
  1127. // If editing a remote job, don't touch the working dir, since we
  1128. // can't expand using its environment variables.
  1129. //
  1130. if (!_JobObjectIsLocal())
  1131. {
  1132. return;
  1133. }
  1134. TCHAR tszWorkingDir[MAX_PATH + 1];
  1135. GetDlgItemText(Hwnd(), txt_workingdir, tszWorkingDir, MAX_PATH + 1);
  1136. StripLeadTrailSpace(tszWorkingDir);
  1137. DeleteQuotes(tszWorkingDir);
  1138. TCHAR tszExpandedWorkingDir[MAX_PATH + 1];
  1139. ULONG cchWritten;
  1140. cchWritten = ExpandEnvironmentStrings(tszWorkingDir,
  1141. tszExpandedWorkingDir,
  1142. ARRAYLEN(tszExpandedWorkingDir));
  1143. //
  1144. // If the call succeeded, write the update string to the working dir
  1145. // edit control. If there were no environment variables to replace,
  1146. // the string will be unchanged.
  1147. //
  1148. // Note that writing to the edit control will cause an EN_CHANGE which
  1149. // will result in m_WorkingDirDirty being set.
  1150. //
  1151. if (cchWritten && cchWritten <= ARRAYLEN(tszExpandedWorkingDir))
  1152. {
  1153. SetDlgItemText(Hwnd(), txt_workingdir, tszExpandedWorkingDir);
  1154. }
  1155. }
  1156. //+--------------------------------------------------------------------------
  1157. //
  1158. // Member: CGeneralPage::_GetAppAndArgs
  1159. //
  1160. // Synopsis: Fetch the string in the application name edit control and
  1161. // split it into the app name part and the arguments part.
  1162. //
  1163. // Arguments: [tszApp] - NULL or buffer for app name
  1164. // [pptszArgs] - NULL or address of pointer to buffer for args,
  1165. // must be deallocated with delete[]
  1166. //
  1167. // Modifies: *[tszApp], *[pptszArgs]
  1168. //
  1169. // History: 1-31-1997 DavidMun Created
  1170. //
  1171. // Notes: Application name is space delimited and must be surrounded
  1172. // by double quotes if it contains spaces. For example:
  1173. //
  1174. // text in edit ctrl 'filename' 'arguments'
  1175. // --------------------- -------------------------
  1176. // notepad.exe foo.txt => 'notepad.exe' 'foo.txt'
  1177. // "notepad.exe"foo.txt => '"notepad.exe"foo.txt' ''
  1178. // "notepad.exe" foo.txt => '"notepad.exe"' 'foo.txt'
  1179. // "no pad.exe" foo.txt => '"no pad.exe"' 'foo.txt'
  1180. // no pad.exe foo.txt => 'no' ' pad.exe foo.txt'
  1181. //
  1182. //---------------------------------------------------------------------------
  1183. VOID
  1184. CGeneralPage::_GetAppAndArgs(
  1185. LPTSTR tszApp,
  1186. LPTSTR * pptszArgs)
  1187. {
  1188. //
  1189. // Split application name into executable name & parameters. First
  1190. // strip lead/trail spaces and null terminate at the first whitespace
  1191. // outside a quote.
  1192. //
  1193. int cch = SchedGetDlgItemTextLength(Hwnd(), txt_app_name) + 1;
  1194. if (cch <= 1)
  1195. {
  1196. DEBUG_OUT((DEB_ERROR,
  1197. "SchedGetDlgItemTextLength failed %d\n",
  1198. GetLastError()));
  1199. }
  1200. TCHAR *ptszBoth = new TCHAR[cch];
  1201. if (ptszBoth == NULL)
  1202. {
  1203. DEBUG_OUT((DEB_ERROR,
  1204. "_GetAppAndArgs alloc failed %d\n",
  1205. GetLastError()));
  1206. return;
  1207. }
  1208. GetDlgItemText(Hwnd(), txt_app_name, ptszBoth, cch);
  1209. StripLeadTrailSpace(ptszBoth);
  1210. LPTSTR ptsz;
  1211. BOOL fInQuote = FALSE;
  1212. for (ptsz = ptszBoth; *ptsz; ptsz = NextChar(ptsz))
  1213. {
  1214. if (*ptsz == TEXT('"'))
  1215. {
  1216. fInQuote = !fInQuote;
  1217. }
  1218. else if (*ptsz == TEXT(' '))
  1219. {
  1220. if (!fInQuote)
  1221. {
  1222. *ptsz++ = L'\0';
  1223. break;
  1224. }
  1225. }
  1226. }
  1227. //
  1228. // Return app name if caller wants it.
  1229. //
  1230. if (tszApp)
  1231. {
  1232. lstrcpy(tszApp, ptszBoth);
  1233. }
  1234. //
  1235. // Now ptsz points to the first char past the application
  1236. // name. If there are no arguments, then ptsz is pointing
  1237. // to the end of the string. Otherwise it's pointing to the
  1238. // start of the argument string. Return this if caller wants it.
  1239. //
  1240. if (pptszArgs)
  1241. {
  1242. *pptszArgs = new TCHAR[cch - (ptsz - ptszBoth)];
  1243. if (*pptszArgs == NULL)
  1244. {
  1245. DEBUG_OUT((DEB_ERROR,
  1246. "_GetAppAndArgs second alloc failed %d\n",
  1247. GetLastError()));
  1248. }
  1249. else
  1250. {
  1251. lstrcpy(*pptszArgs, ptsz);
  1252. }
  1253. }
  1254. delete [] ptszBoth;
  1255. }
  1256. //+--------------------------------------------------------------------------
  1257. //
  1258. // Member: CGeneralPage::_ExpandAppName
  1259. //
  1260. // Synopsis: Change filename in [tszApp] to full path.
  1261. //
  1262. // Arguments: [tszApp] - filename to modify
  1263. //
  1264. // Modifies: *[tszApp]
  1265. //
  1266. // History: 1-31-1997 DavidMun Created
  1267. //
  1268. // Notes: CAUTION: Should be called only for job objects on the
  1269. // LOCAL MACHINE.
  1270. //
  1271. //---------------------------------------------------------------------------
  1272. VOID
  1273. CGeneralPage::_ExpandAppName(
  1274. LPTSTR tszApp)
  1275. {
  1276. TCHAR tszWorkingDir[MAX_PATH + 1];
  1277. BOOL fFound;
  1278. GetDlgItemText(Hwnd(), txt_workingdir, tszWorkingDir, MAX_PATH + 1);
  1279. fFound = ProcessApplicationName(tszApp, tszWorkingDir);
  1280. if (_tcschr(tszApp, TEXT(' ')))
  1281. {
  1282. AddQuotes(tszApp, MAX_PATH);
  1283. }
  1284. }
  1285. //+--------------------------------------------------------------------------
  1286. //
  1287. // Member: CGeneralPage::_SetAppEdit
  1288. //
  1289. // Synopsis: Set the application edit control to contain the concatenated
  1290. // text in [tszApp] and [tszArgs].
  1291. //
  1292. // Arguments: [tszApp] - application name
  1293. // [tszArgs] - arguments
  1294. //
  1295. // History: 1-31-1997 DavidMun Created
  1296. //
  1297. // Notes: No modification (adding quotes, etc.) is done to [tszApp].
  1298. // Caller should set m_ChangeFromSetText = 1 if calling from
  1299. // outside of wm_initdialog processing.
  1300. //
  1301. //---------------------------------------------------------------------------
  1302. VOID
  1303. CGeneralPage::_SetAppEdit(LPCTSTR tszApp, LPCTSTR tszArgs)
  1304. {
  1305. HWND hwndAppName = GetDlgItem(Hwnd(), txt_app_name);
  1306. Edit_SetText(hwndAppName, tszApp);
  1307. if (tszArgs && *tszArgs)
  1308. {
  1309. ULONG cchApp = lstrlen(tszApp);
  1310. Edit_SetSel(hwndAppName, cchApp, cchApp);
  1311. Edit_ReplaceSel(hwndAppName, TEXT(" "));
  1312. Edit_SetSel(hwndAppName, cchApp + 1, cchApp + 1);
  1313. Edit_ReplaceSel(hwndAppName, tszArgs);
  1314. }
  1315. }
  1316. LRESULT CGeneralPage::_OnCancel(void)
  1317. {
  1318. return 0;
  1319. }
  1320. LRESULT
  1321. CGeneralPage::_OnPSMQuerySibling(
  1322. WPARAM wParam,
  1323. LPARAM lParam)
  1324. {
  1325. TRACE(CGeneralPage, _OnPSMQuerySibling);
  1326. INT_PTR iRet = 0;
  1327. switch (wParam)
  1328. {
  1329. case QUERY_READY_TO_BE_SAVED:
  1330. iRet = (int)m_fDirty;
  1331. break;
  1332. case GET_ICON_HELPER:
  1333. iRet = (INT_PTR)m_pIconHelper;
  1334. break;
  1335. #if !defined(_CHICAGO_)
  1336. case QUERY_TASK_APPLICATION_DIRTY_STATUS:
  1337. *((BOOL *)lParam) = m_fTaskApplicationChange;
  1338. iRet = 1;
  1339. break;
  1340. case QUERY_TASK_ACCOUNT_INFO_DIRTY_STATUS:
  1341. *((BOOL *)lParam) = m_fTaskAccountChange;
  1342. iRet = 1;
  1343. break;
  1344. case QUERY_SUPPRESS_ACCOUNT_INFO_REQUEST_FLAG:
  1345. *((BOOL *)lParam) = m_fSuppressAcctInfoRequestOnApply;
  1346. iRet = 1;
  1347. break;
  1348. case RESET_TASK_APPLICATION_DIRTY_STATUS:
  1349. m_fTaskApplicationChange = FALSE;
  1350. iRet = 1;
  1351. break;
  1352. case RESET_TASK_ACCOUNT_INFO_DIRTY_STATUS:
  1353. m_fTaskAccountChange = FALSE;
  1354. iRet = 1;
  1355. break;
  1356. case RESET_SUPPRESS_ACCOUNT_INFO_REQUEST_FLAG:
  1357. m_fSuppressAcctInfoRequestOnApply = FALSE;
  1358. iRet = 1;
  1359. break;
  1360. case TASK_ACCOUNT_CHANGE_NOTIFY:
  1361. Win4Assert(!m_fDirty);
  1362. _UpdateRunAsControl();
  1363. iRet = 1;
  1364. break;
  1365. #endif // !defined(_CHICAGO_)
  1366. }
  1367. SetWindowLongPtr(Hwnd(), DWLP_MSGRESULT, iRet);
  1368. return iRet;
  1369. }
  1370. #if !defined(_CHICAGO_)
  1371. void
  1372. CGeneralPage::_UpdateRunAsControl(void)
  1373. {
  1374. LPWSTR pwsz;
  1375. if (SUCCEEDED(m_pIJob->GetAccountInformation(&pwsz)))
  1376. {
  1377. //
  1378. // Instruct the EN_CHANGE processing of the RunAs edit control
  1379. // to not apply this change.
  1380. //
  1381. m_fApplyRunAsEditChange = FALSE;
  1382. I_SetDlgItemText(Hwnd(), txt_run_as, pwsz);
  1383. m_fApplyRunAsEditChange = TRUE;
  1384. CoTaskMemFree(pwsz);
  1385. }
  1386. }
  1387. #endif // !defined(_CHICAGO_)
  1388. LRESULT
  1389. CGeneralPage::_OnPSNKillActive(
  1390. LPARAM lParam)
  1391. {
  1392. TRACE(CGeneralPage, _OnPSNKillActive);
  1393. if (m_AppNameDirty)
  1394. {
  1395. _UpdateAppNameAndIcon(NULL, NULL);
  1396. }
  1397. if (m_WorkingDirDirty)
  1398. {
  1399. _ExpandWorkingDir();
  1400. }
  1401. return CPropPage::_OnPSNKillActive(lParam);
  1402. }
  1403. LRESULT
  1404. CGeneralPage::_OnHelp(
  1405. HANDLE hRequesting,
  1406. UINT uiHelpCommand)
  1407. {
  1408. WinHelp((HWND)hRequesting,
  1409. szMstaskHelp,
  1410. uiHelpCommand,
  1411. (DWORD_PTR)(LPSTR)s_aGeneralPageHelpIds);
  1412. return TRUE;
  1413. }
  1414. HRESULT
  1415. GetGeneralPage(
  1416. ITask * pIJob,
  1417. LPTSTR ptszTaskPath,
  1418. BOOL fPersistChanges,
  1419. HPROPSHEETPAGE * phpage)
  1420. {
  1421. TRACE_FUNCTION(GetGeneralPage);
  1422. Win4Assert(pIJob != NULL);
  1423. Win4Assert(phpage != NULL);
  1424. HRESULT hr = S_OK;
  1425. LPOLESTR polestr = NULL;
  1426. IPersistFile * ppf = NULL;
  1427. LPTSTR ptszPath = NULL;
  1428. do
  1429. {
  1430. //
  1431. // Get the job name.
  1432. //
  1433. if (ptszTaskPath != NULL)
  1434. {
  1435. //
  1436. // use passed-in path
  1437. //
  1438. ptszPath = ptszTaskPath;
  1439. }
  1440. else
  1441. {
  1442. //
  1443. // Obtain the job path from the interfaces.
  1444. //
  1445. hr = GetJobPath(pIJob, &ptszPath);
  1446. }
  1447. BREAK_ON_FAIL(hr);
  1448. CGeneralPage * pPage = new CGeneralPage(
  1449. pIJob,
  1450. ptszPath,
  1451. fPersistChanges);
  1452. if (pPage == NULL)
  1453. {
  1454. hr = E_OUTOFMEMORY;
  1455. CHECK_HRESULT(hr);
  1456. break;
  1457. }
  1458. HPROPSHEETPAGE hpage = CreatePropertySheetPage(&pPage->m_psp);
  1459. if (hpage == NULL)
  1460. {
  1461. delete pPage;
  1462. hr = E_OUTOFMEMORY;
  1463. CHECK_HRESULT(hr);
  1464. break;
  1465. }
  1466. *phpage = hpage;
  1467. } while (0);
  1468. //
  1469. // If we made a copy of pIJob's path string, free it.
  1470. //
  1471. if (ptszPath != ptszTaskPath)
  1472. {
  1473. delete [] ptszPath;
  1474. }
  1475. if (ppf != NULL)
  1476. {
  1477. ppf->Release();
  1478. }
  1479. return hr;
  1480. }
  1481. HRESULT
  1482. AddGeneralPage(
  1483. PROPSHEETHEADER &psh,
  1484. ITask * pIJob)
  1485. {
  1486. TRACE_FUNCTION(AddGeneralPage);
  1487. HPROPSHEETPAGE hpage = NULL;
  1488. HRESULT hr = GetGeneralPage(pIJob, NULL, TRUE, &hpage);
  1489. if (SUCCEEDED(hr))
  1490. {
  1491. psh.phpage[psh.nPages++] = hpage;
  1492. }
  1493. return hr;
  1494. }
  1495. HRESULT
  1496. AddGeneralPage(
  1497. LPFNADDPROPSHEETPAGE lpfnAddPage,
  1498. LPARAM cookie,
  1499. ITask * pIJob)
  1500. {
  1501. HPROPSHEETPAGE hpage = NULL;
  1502. HRESULT hr = GetGeneralPage(pIJob, NULL, TRUE, &hpage);
  1503. if (SUCCEEDED(hr))
  1504. {
  1505. if (!lpfnAddPage(hpage, cookie))
  1506. {
  1507. DestroyPropertySheetPage(hpage);
  1508. hr = E_FAIL;
  1509. CHECK_HRESULT(hr);
  1510. }
  1511. }
  1512. return hr;
  1513. }
  1514. #if !defined(_CHICAGO_)
  1515. //+---------------------------------------------------------------------------
  1516. //
  1517. // Function: ResetAccountInfo
  1518. //
  1519. // Synopsis: Deallocate and initialize the account information specified.
  1520. //
  1521. // Arguments: [pAccountInfo] -- Account info structure.
  1522. //
  1523. // Returns: None.
  1524. //
  1525. // Notes: None.
  1526. //
  1527. //----------------------------------------------------------------------------
  1528. void
  1529. ResetAccountInfo(
  1530. AccountInfo * pAccountInfo)
  1531. {
  1532. //
  1533. // Delete the account name.
  1534. //
  1535. if (pAccountInfo->pwszAccountName != NULL)
  1536. {
  1537. //
  1538. // NB : pwszAccountName always allocated by CoTaskMemAlloc.
  1539. //
  1540. CoTaskMemFree(pAccountInfo->pwszAccountName);
  1541. pAccountInfo->pwszAccountName = NULL;
  1542. }
  1543. //
  1544. // Zero, delete the password. Except when the password is set to the
  1545. // static empty string.
  1546. //
  1547. if (pAccountInfo->pwszPassword != NULL &&
  1548. pAccountInfo->pwszPassword != tszEmpty)
  1549. {
  1550. ZERO_PASSWORD(pAccountInfo->pwszPassword);
  1551. delete pAccountInfo->pwszPassword;
  1552. pAccountInfo->pwszPassword = (LPWSTR) tszEmpty;
  1553. }
  1554. }
  1555. #endif // !defined(_CHICAGO_)
  1556. #if !defined(_CHICAGO_)
  1557. //+---------------------------------------------------------------------------
  1558. //
  1559. // Function: InitializeAccountInfo
  1560. //
  1561. // Synopsis: Initializes account info fields.
  1562. //
  1563. // Arguments: [pAccountInfo] -- Account info structure.
  1564. //
  1565. // Returns: None.
  1566. //
  1567. // Notes: None.
  1568. //
  1569. //----------------------------------------------------------------------------
  1570. void
  1571. InitializeAccountInfo(AccountInfo * pAccountInfo)
  1572. {
  1573. pAccountInfo->pwszAccountName = NULL;
  1574. //
  1575. // If we haven't prompted for a password, pwszPassword points to the
  1576. // global empty string variable. This allows us to tell whether the
  1577. // user intended the password to be an empty string, or we simply
  1578. // haven't prompted for it.
  1579. //
  1580. pAccountInfo->pwszPassword = (LPWSTR) tszEmpty;
  1581. }
  1582. #endif // !defined(_CHICAGO_)
  1583. //
  1584. // Helpers to launch Set/Change Password & Set Account Information dialogs.
  1585. //
  1586. #if !defined(_CHICAGO_)
  1587. //+---------------------------------------------------------------------------
  1588. //
  1589. // Function: LaunchSetPasswordDlg
  1590. //
  1591. // Synopsis: Helper to launch the dialog to modify the account password.
  1592. //
  1593. // Arguments: [hWnd] -- Parent window handle.
  1594. // [pAccountInfo] -- Structure manipulated by the dialog.
  1595. //
  1596. // Returns: DialogBoxParam return code.
  1597. //
  1598. // Notes: None.
  1599. //
  1600. //----------------------------------------------------------------------------
  1601. INT_PTR
  1602. LaunchSetPasswordDlg(HWND hWnd, AccountInfo * pAccountInfo)
  1603. {
  1604. return(DialogBoxParam(g_hInstance,
  1605. MAKEINTRESOURCE(set_passwd_dlg),
  1606. hWnd,
  1607. SetPasswordDlgProc,
  1608. (LPARAM)pAccountInfo));
  1609. }
  1610. #endif // !defined(_CHICAGO_)
  1611. #if !defined(_CHICAGO_)
  1612. //+---------------------------------------------------------------------------
  1613. //
  1614. // Function: LaunchSetAccountInformationDlg
  1615. //
  1616. // Synopsis: Helper to launch the dialog to modify the account namd and
  1617. // password.
  1618. //
  1619. // Arguments: [hWnd] -- Parent window handle.
  1620. // [pAccountInfo] -- Structure manipulated by the dialog.
  1621. //
  1622. // Returns: DialogBoxParam return code.
  1623. //
  1624. // Notes: None.
  1625. //
  1626. //----------------------------------------------------------------------------
  1627. INT_PTR
  1628. LaunchSetAccountInformationDlg(HWND hWnd, AccountInfo * pAccountInfo)
  1629. {
  1630. return(DialogBoxParam(g_hInstance,
  1631. MAKEINTRESOURCE(set_account_info_dlg),
  1632. hWnd,
  1633. SetAccountInformationDlgProc,
  1634. (LPARAM)pAccountInfo));
  1635. }
  1636. #endif // !defined(_CHICAGO_)
  1637. //
  1638. // Set/Change Password & Set Account Information dialogs.
  1639. //
  1640. #if !defined(_CHICAGO_)
  1641. //+---------------------------------------------------------------------------
  1642. //
  1643. // Function: SetPasswordDlgProc
  1644. //
  1645. // Synopsis: This dialog allows the user specify an account password.
  1646. // The password is confirmed by a redundant confirmation edit
  1647. // field.
  1648. //
  1649. // Arguments: [hDlg] -- Dialog handle.
  1650. // [uMsg] -- Message.
  1651. // [wParam] -- Command.
  1652. // [lParam] -- Account information dialog ptr on WM_INITDIALOG.
  1653. //
  1654. // Returns: TRUE -- Message processed by this dialog.
  1655. // FALSE -- Message not processed (WM_INITDIALOG excepted).
  1656. //
  1657. // Notes: None.
  1658. //
  1659. //----------------------------------------------------------------------------
  1660. INT_PTR APIENTRY
  1661. SetPasswordDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1662. {
  1663. static AccountInfo * pai = NULL;
  1664. TCHAR tszPassword[MAX_PASSWORD + 1] = TEXT("");
  1665. TCHAR tszConfirmedPassword[MAX_PASSWORD + 1] = TEXT("");
  1666. LPWSTR pwszPassword;
  1667. switch (uMsg)
  1668. {
  1669. case WM_INITDIALOG:
  1670. Win4Assert(lParam != NULL);
  1671. pai = (AccountInfo *)lParam;
  1672. Edit_LimitText(GetDlgItem(hDlg, edt_sp_passwd), MAX_PASSWORD);
  1673. Edit_LimitText(GetDlgItem(hDlg, edt_sp_cfrmpasswd), MAX_PASSWORD);
  1674. I_SetDlgItemText(hDlg, edt_sp_passwd, pai->pwszPassword);
  1675. I_SetDlgItemText(hDlg, edt_sp_cfrmpasswd, pai->pwszPassword);
  1676. //
  1677. // Center the dialog.
  1678. //
  1679. CenterDialog(hDlg);
  1680. return TRUE; // TRUE == let windows set focus
  1681. case WM_COMMAND:
  1682. switch(LOWORD(wParam))
  1683. {
  1684. case IDOK:
  1685. DWORD ccPassword;
  1686. ccPassword = GetDlgItemText(hDlg,
  1687. edt_sp_passwd,
  1688. tszPassword,
  1689. MAX_PASSWORD + 1);
  1690. GetDlgItemText(hDlg,
  1691. edt_sp_cfrmpasswd,
  1692. tszConfirmedPassword,
  1693. MAX_PASSWORD + 1);
  1694. if (lstrcmp(tszPassword, tszConfirmedPassword) != 0)
  1695. {
  1696. //
  1697. // Passwords didn't match. Let the user know so he/she
  1698. // can correct it.
  1699. //
  1700. ZeroMemory(tszPassword, sizeof tszPassword);
  1701. ZeroMemory(tszConfirmedPassword, sizeof tszConfirmedPassword);
  1702. SchedUIErrorDialog(hDlg, IERR_PASSWORD, (LPTSTR)NULL);
  1703. return(TRUE);
  1704. }
  1705. if (ccPassword)
  1706. {
  1707. //
  1708. // Non-NULL password.
  1709. //
  1710. ccPassword++;
  1711. pwszPassword = new WCHAR[ccPassword];
  1712. if (pwszPassword != NULL)
  1713. {
  1714. #if !defined(UNICODE)
  1715. HRESULT hr = AnsiToUnicode(pwszPassword,
  1716. tszPassword,
  1717. ccPassword);
  1718. if (FAILED(hr))
  1719. {
  1720. SchedUIErrorDialog(hDlg,
  1721. IERR_INTERNAL_ERROR,
  1722. 0);
  1723. ZERO_PASSWORD(pwszPassword);
  1724. delete [] pwszPassword;
  1725. ZeroMemory(tszPassword, sizeof tszPassword);
  1726. ZeroMemory(tszConfirmedPassword,
  1727. sizeof tszConfirmedPassword);
  1728. return(TRUE);
  1729. }
  1730. #else
  1731. lstrcpy(pwszPassword, tszPassword);
  1732. #endif // !defined(UNICODE)
  1733. }
  1734. else
  1735. {
  1736. SchedUIErrorDialog(hDlg, IERR_OUT_OF_MEMORY,
  1737. (LPTSTR)NULL);
  1738. }
  1739. }
  1740. else
  1741. {
  1742. //
  1743. // Clear the password.
  1744. //
  1745. pwszPassword = new WCHAR[1];
  1746. if (pwszPassword != NULL)
  1747. {
  1748. *pwszPassword = L'\0';
  1749. }
  1750. else
  1751. {
  1752. SchedUIErrorDialog(hDlg, IERR_OUT_OF_MEMORY,
  1753. (LPTSTR)NULL);
  1754. EndDialog(hDlg, wParam);
  1755. return(TRUE);
  1756. }
  1757. }
  1758. //
  1759. // Zero, delete the previous password. But don't delete the
  1760. // static empty string.
  1761. //
  1762. if (pai->pwszPassword != NULL &&
  1763. pai->pwszPassword != tszEmpty)
  1764. {
  1765. ZERO_PASSWORD(pai->pwszPassword);
  1766. delete pai->pwszPassword;
  1767. }
  1768. pai->pwszPassword = pwszPassword;
  1769. case IDCANCEL:
  1770. ZeroMemory(tszPassword, sizeof tszPassword);
  1771. ZeroMemory(tszConfirmedPassword, sizeof tszConfirmedPassword);
  1772. EndDialog(hDlg, wParam);
  1773. return TRUE;
  1774. default:
  1775. return FALSE;
  1776. }
  1777. case WM_HELP:
  1778. WinHelp((HWND) ((LPHELPINFO) lParam)->hItemHandle,
  1779. szMstaskHelp,
  1780. HELP_WM_HELP,
  1781. (DWORD_PTR)(LPSTR)s_aSetPasswordDlgHelpIds);
  1782. return TRUE;
  1783. case WM_CONTEXTMENU:
  1784. WinHelp((HWND) wParam,
  1785. szMstaskHelp,
  1786. HELP_CONTEXTMENU,
  1787. (DWORD_PTR)(LPSTR)s_aSetPasswordDlgHelpIds);
  1788. return TRUE;
  1789. default:
  1790. return FALSE;
  1791. }
  1792. }
  1793. #endif // !defined(_CHICAGO_)
  1794. #if !defined(_CHICAGO_)
  1795. //+---------------------------------------------------------------------------
  1796. //
  1797. // Function: SetAccountInformationDlgProc
  1798. //
  1799. // Synopsis: This dialog allows the user to specify full account
  1800. // information: the account name and password. The password
  1801. // is confirmed by a redundant confirmation edit field.
  1802. // Logic also ensures the user must specify an account name.
  1803. //
  1804. // Arguments: [hDlg] -- Dialog handle.
  1805. // [uMsg] -- Message.
  1806. // [wParam] -- Command.
  1807. // [lParam] -- Account information dialog ptr on WM_INITDIALOG.
  1808. //
  1809. // Returns: TRUE -- Message processed by this dialog.
  1810. // FALSE -- Message not processed (WM_INITDIALOG excepted).
  1811. //
  1812. // Notes: None.
  1813. //
  1814. //----------------------------------------------------------------------------
  1815. INT_PTR APIENTRY
  1816. SetAccountInformationDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
  1817. LPARAM lParam)
  1818. {
  1819. static AccountInfo * pai = NULL;
  1820. TCHAR tszAccountName[MAX_USERNAME + 1] = TEXT("");
  1821. TCHAR tszPassword[MAX_PASSWORD + 1] = TEXT("");
  1822. TCHAR tszConfirmedPassword[MAX_PASSWORD + 1] = TEXT("");
  1823. DWORD ccAccountName = MAX_USERNAME + 1;
  1824. LPWSTR pwszPassword;
  1825. switch (uMsg)
  1826. {
  1827. case WM_INITDIALOG:
  1828. Win4Assert(lParam != NULL);
  1829. pai = (AccountInfo *)lParam;
  1830. Edit_LimitText(GetDlgItem(hDlg, edt_sa_passwd), MAX_USERNAME);
  1831. Edit_LimitText(GetDlgItem(hDlg, edt_sa_passwd), MAX_PASSWORD);
  1832. Edit_LimitText(GetDlgItem(hDlg, edt_sa_cfrmpasswd), MAX_PASSWORD);
  1833. if (pai->pwszAccountName != NULL)
  1834. {
  1835. #if !defined(UNICODE)
  1836. //
  1837. // Even if conversion fails, tszAccountName will be terminated,
  1838. // so put it in the UI regardless.
  1839. //
  1840. ZeroMemory(tszAccountName, ARRAYLEN(tszAccountName));
  1841. (void) UnicodeToAnsi(tszAccountName, pai->pwszAccountName,
  1842. ccAccountName);
  1843. #else
  1844. lstrcpy(tszAccountName, pai->pwszAccountName);
  1845. #endif // !defined(UNICODE)
  1846. }
  1847. else
  1848. {
  1849. GetDefaultDomainAndUserName(tszAccountName, ccAccountName);
  1850. }
  1851. SetDlgItemText(hDlg, txt_sa_run_as, tszAccountName);
  1852. I_SetDlgItemText(hDlg, edt_sa_passwd, pai->pwszPassword);
  1853. I_SetDlgItemText(hDlg, edt_sa_cfrmpasswd, pai->pwszPassword);
  1854. //
  1855. // Center the dialog.
  1856. //
  1857. CenterDialog(hDlg);
  1858. return TRUE; // TRUE == let windows set focus
  1859. case WM_COMMAND:
  1860. switch(LOWORD(wParam))
  1861. {
  1862. case IDOK:
  1863. DWORD ccAccountName, ccPassword;
  1864. tszAccountName[0] = _T('\0');
  1865. ccAccountName = GetDlgItemText(hDlg, txt_sa_run_as,
  1866. tszAccountName, MAX_USERNAME + 1);
  1867. if (tszAccountName[0] != _T('\0'))
  1868. {
  1869. ccAccountName++;
  1870. LPWSTR pwszAccountName = (LPWSTR)CoTaskMemAlloc(
  1871. ccAccountName * sizeof(WCHAR));
  1872. if (pwszAccountName != NULL)
  1873. {
  1874. #if !defined(UNICODE)
  1875. HRESULT hr = AnsiToUnicode(pwszAccountName,
  1876. tszAccountName,
  1877. ccAccountName);
  1878. if (FAILED(hr))
  1879. {
  1880. CoTaskMemFree(pwszAccountName);
  1881. SchedUIErrorDialog(hDlg, IERR_INTERNAL_ERROR, 0);
  1882. break;
  1883. }
  1884. #else
  1885. lstrcpy(pwszAccountName, tszAccountName);
  1886. #endif // !defined(UNICODE)
  1887. ccPassword = GetDlgItemText(hDlg, edt_sa_passwd,
  1888. tszPassword,
  1889. MAX_PASSWORD + 1);
  1890. GetDlgItemText(hDlg, edt_sa_cfrmpasswd,
  1891. tszConfirmedPassword, MAX_PASSWORD + 1);
  1892. if (lstrcmp(tszPassword, tszConfirmedPassword) != 0)
  1893. {
  1894. //
  1895. // Passwords didn't match. Let the user know so he/she
  1896. // can correct it.
  1897. //
  1898. CoTaskMemFree(pwszAccountName);
  1899. SchedUIErrorDialog(hDlg, IERR_PASSWORD,
  1900. (LPTSTR)NULL);
  1901. return(TRUE);
  1902. }
  1903. else
  1904. {
  1905. if (ccPassword)
  1906. {
  1907. //
  1908. // Non-NULL password.
  1909. //
  1910. ccPassword++;
  1911. pwszPassword = new WCHAR[ccPassword];
  1912. if (pwszPassword != NULL)
  1913. {
  1914. #if !defined(UNICODE)
  1915. HRESULT hr = AnsiToUnicode(pwszPassword,
  1916. tszPassword,
  1917. ccPassword);
  1918. if (FAILED(hr))
  1919. {
  1920. CoTaskMemFree(pwszAccountName);
  1921. SchedUIErrorDialog(hDlg,
  1922. IERR_INTERNAL_ERROR,
  1923. 0);
  1924. return(TRUE);
  1925. }
  1926. #else
  1927. lstrcpy(pwszPassword, tszPassword);
  1928. #endif // !defined(UNICODE)
  1929. }
  1930. else
  1931. {
  1932. CoTaskMemFree(pwszAccountName);
  1933. SchedUIErrorDialog(hDlg, IERR_OUT_OF_MEMORY,
  1934. (LPTSTR)NULL);
  1935. EndDialog(hDlg, wParam);
  1936. return(TRUE);
  1937. }
  1938. }
  1939. else
  1940. {
  1941. //
  1942. // Clear the password.
  1943. //
  1944. pwszPassword = new WCHAR[1];
  1945. if (pwszPassword != NULL)
  1946. {
  1947. *pwszPassword = L'\0';
  1948. }
  1949. else
  1950. {
  1951. CoTaskMemFree(pwszAccountName);
  1952. SchedUIErrorDialog(hDlg, IERR_OUT_OF_MEMORY,
  1953. (LPTSTR)NULL);
  1954. EndDialog(hDlg, wParam);
  1955. return(TRUE);
  1956. }
  1957. }
  1958. }
  1959. if (pai->pwszAccountName != NULL)
  1960. {
  1961. CoTaskMemFree(pai->pwszAccountName);
  1962. }
  1963. if (pai->pwszPassword != NULL &&
  1964. pai->pwszPassword != tszEmpty)
  1965. {
  1966. ZERO_PASSWORD(pai->pwszPassword);
  1967. delete pai->pwszPassword;
  1968. }
  1969. pai->pwszAccountName = pwszAccountName;
  1970. pai->pwszPassword = pwszPassword;
  1971. }
  1972. else
  1973. {
  1974. SchedUIErrorDialog(hDlg, IERR_OUT_OF_MEMORY,
  1975. (LPTSTR)NULL);
  1976. }
  1977. }
  1978. else
  1979. {
  1980. //
  1981. // User cannot specify an empty account name.
  1982. //
  1983. SchedUIErrorDialog(hDlg, IERR_ACCOUNTNAME, (LPTSTR)NULL);
  1984. return(TRUE);
  1985. }
  1986. case IDCANCEL:
  1987. EndDialog(hDlg, wParam);
  1988. return TRUE;
  1989. }
  1990. default:
  1991. return FALSE;
  1992. }
  1993. }
  1994. #endif // !defined(_CHICAGO_)
  1995. #if !defined(_CHICAGO_)
  1996. //+---------------------------------------------------------------------------
  1997. //
  1998. // Function: CenterDialog
  1999. //
  2000. // Synopsis: Helper to center a dialog on screen.
  2001. //
  2002. // Arguments: [hDlg] -- Dialog handle.
  2003. //
  2004. // Returns: None.
  2005. //
  2006. // Notes: None.
  2007. //
  2008. //----------------------------------------------------------------------------
  2009. void
  2010. CenterDialog(HWND hDlg)
  2011. {
  2012. RECT rc;
  2013. GetWindowRect(hDlg, &rc);
  2014. SetWindowPos(hDlg,
  2015. NULL,
  2016. ((GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) / 2),
  2017. ((GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) / 2),
  2018. 0,
  2019. 0,
  2020. SWP_NOSIZE | SWP_NOACTIVATE);
  2021. }
  2022. #endif // !defined(_CHICAGO_)
  2023. //+---------------------------------------------------------------------------
  2024. //
  2025. // Function: SchedGetDlgItemTextLength
  2026. //
  2027. // Synopsis: Implements a GetDlgItemTextLength function since Win32 lacks it
  2028. //
  2029. // Arguments:
  2030. //
  2031. // Returns:
  2032. //
  2033. //----------------------------------------------------------------------------
  2034. int
  2035. SchedGetDlgItemTextLength(
  2036. HWND hwnd,
  2037. int id)
  2038. {
  2039. if ((hwnd = GetDlgItem(hwnd, id)) != NULL)
  2040. {
  2041. return GetWindowTextLength(hwnd);
  2042. }
  2043. return 0;
  2044. }