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.

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