|
|
//____________________________________________________________________________
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1995 - 1996.
//
// File: general.cxx
//
// Contents:
//
// Classes:
//
// Functions:
//
// Notes: For the first release of the scheduling agent, all security
// operations are disabled under Win95, even Win95 to NT.
//
// History: 3/4/1996 RaviR Created
// 1-30-1997 DavidMun params edit becomes working dir
// 02/29/01 JBenton BUG 280401 app icon was not being updated
// on prop sheet in case of service not running
//
//____________________________________________________________________________
#include "..\pch\headers.hxx"
#pragma hdrstop
#include "..\inc\dll.hxx"
#include "..\folderui\dbg.h"
#include "..\folderui\macros.h"
#include "dlg.hxx"
#include "..\folderui\jobicons.hxx"
#include "..\inc\resource.h"
#include "..\inc\defines.hxx"
#include "..\inc\common.hxx"
#include "..\inc\misc.hxx"
#include "..\inc\policy.hxx"
#include <StrSafe.h>
#define SECURITY_WIN32
#include <security.h> // GetUserNameEx
#undef SECURITY_WIN32
#include "SASecRPC.h" // SASetNSAccountInformation RPC definition.
#include "..\inc\network.hxx"
#include "rc.h"
#include "defines.h"
#include <mstask.h>
#include "uiutil.hxx"
#include "commdlg.h"
#include "helpids.h"
#include "iconhlpr.hxx"
#include "schedui.hxx"
//
// extern
//
extern HINSTANCE g_hInstance;
//
// Forward references
//
// CenterDialog - Centers a dialog on screen. Used by the security-related
// subdialogs.
//
void CenterDialog(HWND hDlg);
void GetDefaultDomainAndUserName( LPTSTR ptszDomainAndUserName, ULONG cchBuf);
//
// Launches the modal set password dialog.
//
INT_PTR LaunchSetPasswordDlg( HWND hWnd, AccountInfo * pAccountInfo);
INT_PTR APIENTRY SetPasswordDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR APIENTRY SetAccountInformationDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
int SchedGetDlgItemTextLength( HWND hwnd, int id);
//
// (Control id, help id) list for context sensitivity help.
//
ULONG s_aGeneralPageHelpIds[] = { idc_icon, Hidc_icon, lbl_job_name, Hlbl_job_name, lbl_comments, Hlbl_comments, txt_comments, Htxt_comments, lbl_app_name, Hlbl_app_name, txt_app_name, Htxt_app_name, btn_browse, Hbtn_browse, lbl_workingdir, Hlbl_workingdir, txt_workingdir, Htxt_workingdir, lbl_run_as, Hlbl_execute_as, txt_run_as, Htxt_execute_as, btn_passwd, Hbtn_passwd, chk_enable_job, Hchk_enable_job, btn_settings, Hbtn_settings, 0,0 };
const ULONG s_aSetPasswordDlgHelpIds[] = { set_passwd_dlg, Hset_passwd_dlg, lbl_sp_passwd, Hlbl_sp_passwd, edt_sp_passwd, Hedt_sp_passwd, lbl_sp_cfrmpasswd, Hlbl_sp_cfrmpasswd, edt_sp_cfrmpasswd, Hedt_sp_cfrmpasswd, 0,0 };
extern "C" TCHAR szMstaskHelp[];
const TCHAR SAGERUN_PARAM[] = TEXT("/SAGERUN:");
TCHAR szMstaskHelp[] = TEXT("%windir%\\help\\mstask.hlp");
//____________________________________________________________________________
//____________________________________________________________________________
//________________ ______________________________________
//________________ class CGeneralPage ______________________________________
//________________ ______________________________________
//____________________________________________________________________________
//____________________________________________________________________________
class CGeneralPage : public CPropPage { public:
CGeneralPage(ITask * pIJob, LPTSTR ptszTaskPath, BOOL fPersistChanges);
~CGeneralPage();
private:
virtual LRESULT _OnInitDialog(LPARAM lParam); virtual LRESULT _OnCommand(int id, HWND hwndCtl, UINT codeNotify); virtual LRESULT _OnApply(void); virtual LRESULT _OnCancel(void); virtual LRESULT _OnPSMQuerySibling(WPARAM wParam, LPARAM lParam); virtual LRESULT _OnPSNKillActive(LPARAM lParam); virtual LRESULT _OnHelp(HANDLE hRequesting, UINT uiHelpCommand);
VOID _ExpandAppName(LPTSTR tszApp, size_t cchBuff); VOID _ExpandWorkingDir(); VOID _GetAppAndArgs(LPTSTR tszApp, size_t appBufSize, LPTSTR * pptszArg); VOID _UpdateAppNameAndIcon(LPWSTR wszApp, size_t appBufSize, LPWSTR * ppwszArg); VOID _UpdateAppIcon(LPCTSTR tszApp); VOID _SetAppEdit(LPCTSTR tszApp, LPCTSTR tszArgs); BOOL _JobObjectIsLocal(); void _UpdateRunAsControl(void); BOOL _Browse(TCHAR szFilePath[]);
void _ErrorDialog(int idsErr, LONG error = 0, UINT idsHelpHint = 0) { SchedUIErrorDialog(Hwnd(), idsErr, error, idsHelpHint); }
void _DisableUI(void);
AccountInfo m_AccountInfo; // Account/password change info.
ITask * m_pIJob;
// Flag values. Note the compiler allocates a single dword for these
DWORD m_CommentDirty : 1; //
DWORD m_AppNameDirty : 1; //
DWORD m_WorkingDirDirty : 1; // A value of 1 => dirty
DWORD m_RunAsDirty : 1; //
DWORD m_updateIcon : 1; // 1 => update needed
DWORD m_ChangeFromSetText : 1;// 0 => en_change from user
//
// icon helper
//
CIconHelper * m_pIconHelper;
//
// flags
//
BOOL m_fPersistChanges; // Should we save on Apply or OK?
BOOL m_fEnableJob; // Is the job enabled?
BOOL m_fNetScheduleJob; // Is this an AT job?
//
// Saved or new sage settings parameter
//
TCHAR m_tszSageRunParam[20]; // /SAGERUN:4294967295
//
// The RunAs edit control can be updated by the user, or automatically
// with apply via the set account information dialog. In response to
// user edits, we want to apply the changes. For the automatic RunAs
// update, we've already applied the changes, therefore, this flag
// exists to not re-dirty the page.
//
BOOL m_fApplyRunAsEditChange;
//
// The other pages need to query the general page if there is an
// application or security account change for the common security
// code in the page's save path (JFSaveJob). The record of this
// dirty information must be retained post-Apply; therefore, these
// slightly redundant flags are necessary.
//
BOOL m_fTaskApplicationChange; BOOL m_fTaskAccountChange;
//
// Set this flag to TRUE if we have launched the set password dialog.
// Othwerwise, the user may get a redundant set account information
// dialog on apply.
//
BOOL m_fSuppressAcctInfoRequestOnApply;
}; // class CGeneralPage
inline CGeneralPage::CGeneralPage( ITask * pIJob, LPTSTR ptszTaskPath, BOOL fPersistChanges) : m_pIJob(pIJob), m_pIconHelper(NULL), m_fPersistChanges(fPersistChanges), m_ChangeFromSetText(FALSE), m_fApplyRunAsEditChange(TRUE), m_fTaskApplicationChange(FALSE), m_fTaskAccountChange(FALSE), m_fSuppressAcctInfoRequestOnApply(FALSE), m_fNetScheduleJob(FALSE), CPropPage(MAKEINTRESOURCE(general_page), ptszTaskPath) { TRACE(CGeneralPage, CGeneralPage);
Win4Assert(m_pIJob != NULL);
m_pIJob->AddRef(); m_tszSageRunParam[0] = TEXT('\0');
InitializeAccountInfo(&m_AccountInfo); }
inline CGeneralPage::~CGeneralPage() { TRACE(CGeneralPage, ~CGeneralPage);
if (m_pIconHelper != NULL) { m_pIconHelper->Release(); }
if (m_pIJob != NULL) { m_pIJob->Release(); }
ResetAccountInfo(&m_AccountInfo); }
//+--------------------------------------------------------------------------
//
// Member: CGeneralPage::_JobObjectIsLocal
//
// Synopsis: Return TRUE if job object being edited lives on the local
// machine, FALSE otherwise.
//
// History: 2-01-1997 DavidMun Created
//
//---------------------------------------------------------------------------
inline BOOL CGeneralPage::_JobObjectIsLocal() { return IsLocalFilename(GetTaskPath()); }
LRESULT CGeneralPage::_OnInitDialog( LPARAM lParam) { TRACE(CGeneralPage, _OnInitDialog);
HRESULT hr = S_OK; LPWSTR pwsz = NULL; BOOL fEnableSecurity = FALSE; TCHAR tszApp[MAX_PATH + 1] = TEXT("");
//
// Note that we don't limit the txt_app_name control. App names are
// limited to MAX_PATH characters, but app parameters are not.
//
HWND hwnd; if (hwnd = _hCtrl(txt_comments)) Edit_LimitText(hwnd, MAX_PATH); if (hwnd = _hCtrl(txt_workingdir)) Edit_LimitText(hwnd, MAX_PATH); if (hwnd = _hCtrl(txt_run_as)) Edit_LimitText(hwnd, MAX_USERNAME);
//
// Policy - if this reg key is valid, disable browse
//
if (RegReadPolicyKey(TS_KEYPOLICY_DENY_BROWSE)) { DEBUG_OUT((DEB_ITRACE, "Policy ALLOW_BROWSE active, no browse or edit\n")); if (hwnd = _hCtrl(btn_browse)) EnableWindow(hwnd, FALSE); if (hwnd = _hCtrl(btn_browse)) ShowWindow(hwnd, SW_HIDE); if (hwnd = _hCtrl(txt_app_name)) EnableWindow(hwnd, FALSE); if (hwnd = _hCtrl(txt_workingdir)) EnableWindow(hwnd, FALSE); }
do { // Determine if the security settings should be shown or not.
// The task object must reside within a tasks folder & exist
// on an NT machine.
//
fEnableSecurity = (this->GetPlatformId() == VER_PLATFORM_WIN32_NT && this->IsTaskInTasksFolder());
if (!fEnableSecurity) { if (hwnd = _hCtrl(lbl_run_as)) DestroyWindow(hwnd); if (hwnd = _hCtrl(txt_run_as)) DestroyWindow(hwnd); if (hwnd = _hCtrl(btn_passwd)) DestroyWindow(hwnd); }
//
// Set the job enabled check box
//
DWORD dwFlags; hr = m_pIJob->GetFlags(&dwFlags); m_fEnableJob = (dwFlags & TASK_FLAG_DISABLED) ? FALSE : TRUE; CheckDlgButton(m_hPage, chk_enable_job, m_fEnableJob);
//
// Remember this for use later
//
m_fNetScheduleJob = dwFlags & JOB_I_FLAG_NET_SCHEDULE;
// See if the schedule page has already created the icon
// helper, if not create it here.
m_pIconHelper = (CIconHelper *)PropSheet_QuerySiblings( GetParent(Hwnd()), GET_ICON_HELPER, 0);
if (m_pIconHelper == NULL) { m_pIconHelper = new CIconHelper();
if (m_pIconHelper == NULL) { hr = E_OUTOFMEMORY; break; } } else { m_pIconHelper->AddRef(); }
//
// Set job name (static text showing path to .job object)
//
SetDlgItemText(Hwnd(), lbl_job_name, this->GetTaskPath());
//
// Set comments
//
hr = m_pIJob->GetComment(&pwsz);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
I_SetDlgItemText(Hwnd(), txt_comments, pwsz); CoTaskMemFree(pwsz);
//
// Get application name preparatory to setting it.
//
hr = m_pIJob->GetApplicationName(&pwsz);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
lstrcpyn(tszApp, pwsz, MAX_PATH + 1);
//
// If the application name fetched from the job object has spaces in
// it, add quotes around the tchar version.
//
if (wcschr(pwsz, L' ')) { AddQuotes(tszApp, MAX_PATH + 1); } CoTaskMemFree(pwsz);
//
// Now get the parameters and append a space and the tchar
// representation to the app name.
//
hr = m_pIJob->GetParameters(&pwsz); CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
TCHAR * tszArg = pwsz;
//
// If the /SAGERUN:n parameter appears in the arguments, save it in
// an internal buffer, but don't show it in the UI.
//
LPTSTR ptszSageRun = _tcsstr(tszArg, SAGERUN_PARAM);
if (ptszSageRun) { lstrcpyn(m_tszSageRunParam, ptszSageRun, ARRAYLEN(m_tszSageRunParam));
*ptszSageRun = TEXT('\0'); StripLeadTrailSpace(tszArg); // get rid of spaces before /sagerun
}
_SetAppEdit(tszApp, tszArg);
CoTaskMemFree(pwsz);
//
// Set the working directory
//
hr = m_pIJob->GetWorkingDirectory(&pwsz); CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
if (wcschr(pwsz, L' ')) { WCHAR wszWorkingDir[MAX_PATH + 1] = L"\"";
wcsncpy(wszWorkingDir + 1, pwsz, MAX_PATH - 1); StringCchCat(wszWorkingDir, MAX_PATH + 1, L"\""); I_SetDlgItemText(Hwnd(), txt_workingdir, wszWorkingDir); } else { I_SetDlgItemText(Hwnd(), txt_workingdir, pwsz); } CoTaskMemFree(pwsz);
if (!this->IsTaskInTasksFolder()) { EnableWindow(_hCtrl(chk_enable_job), FALSE); m_fEnableJob = FALSE; }
if (fEnableSecurity) { //
// Set account name (run as)
//
DWORD cchAccount = MAX_USERNAME + 1; WCHAR wszDisplayAccount[MAX_USERNAME + 1] = L"";
hr = m_pIJob->GetAccountInformation(&pwsz); if (SUCCEEDED(hr)) { //
// Translate account prior to display, then display it
//
hr = TranslateAccount(TRANSLATE_FOR_DISPLAY, pwsz, wszDisplayAccount, cchAccount); if (SUCCEEDED(hr)) { I_SetDlgItemText(Hwnd(), txt_run_as, wszDisplayAccount); // display the translated account
} m_AccountInfo.pwszAccountName = pwsz; // use the untranslated account internally
EnableWindow(_hCtrl(btn_passwd), TRUE); } else if (hr == SCHED_E_ACCOUNT_INFORMATION_NOT_SET) { WCHAR wszAccount[MAX_USERNAME + 1]; if (m_fNetScheduleJob) { //
// get the name of the AT service account
//
RpcTryExcept { hr = SAGetNSAccountInformation(NULL, cchAccount, wszAccount); } RpcExcept(1) { DWORD Status = RpcExceptionCode(); hr = SchedMapRpcError(Status); } RpcEndExcept; if (FAILED(hr) || S_FALSE == hr) { wszAccount[0] = L'\0'; } } else { //
// Set the run as field to the current user's name and
// enable the set/change password button.
//
GetDefaultDomainAndUserName(wszAccount, cchAccount); //
// Sometimes I think this would be better than defaulting to the current user, because
// the user can get confused and think that the account is already set when it isn't.
//
// lstrcpyW(wszAccount,L"***Account not set***");
//
}
//
// Translate account prior to display, then display it
//
hr = TranslateAccount(TRANSLATE_FOR_DISPLAY, wszAccount, wszDisplayAccount, cchAccount); if (SUCCEEDED(hr)) { SetDlgItemText(Hwnd(), txt_run_as, wszDisplayAccount); } EnableWindow(_hCtrl(btn_passwd), TRUE);
//
// everything is ok, really
//
hr = S_OK; } else { //
// Disable the run as and set/change password button ctrls &
// put up an error dialog letting the user know that security
// services are unavailable.
//
// Actually, the set/change password button is already
// disabled.
//
CHECK_HRESULT(hr); EnableWindow(_hCtrl(lbl_run_as), FALSE); EnableWindow(_hCtrl(txt_run_as), FALSE); } }
} while (0);
//
// Disable all controls if this is an AT job
// to prevent user from making changes
//
if (m_fNetScheduleJob) _DisableUI();
if (FAILED(hr)) { if (hr == E_OUTOFMEMORY) { _ErrorDialog(IERR_OUT_OF_MEMORY); } else { _ErrorDialog(IERR_GENERAL_PAGE_INIT, hr); }
//
// Show application icon
//
m_updateIcon = 1; _UpdateAppIcon(tszApp);
EnableWindow(Hwnd(), FALSE);
return FALSE; }
//
// Show application icon
//
m_updateIcon = 1; _UpdateAppIcon(tszApp);
//
// Need to initialize these here since doing a SetDlgItemText causes
// a WM_COMMAND msg with EN_CHANGE to be called for edit boxes.
//
m_CommentDirty = 0; m_AppNameDirty = 0; m_WorkingDirDirty = 0; m_RunAsDirty = 0;
m_fDirty = FALSE;
return TRUE; }
//+--------------------------------------------------------------------------
//
// Member: CGeneralPage::_DisableUI
//
// Synopsis: Disable UI so the user can only view the settings
//
// History: 2001-11-13 ShBrown Created
//
//---------------------------------------------------------------------------
void CGeneralPage::_DisableUI(void) { HWND hwnd; if (hwnd = _hCtrl(txt_app_name)) EnableWindow(hwnd, FALSE); if (hwnd = _hCtrl(txt_workingdir)) EnableWindow(hwnd, FALSE); if (hwnd = _hCtrl(txt_comments)) EnableWindow(hwnd, FALSE); if (hwnd = _hCtrl(txt_run_as)) EnableWindow(hwnd, FALSE); if (hwnd = _hCtrl(chk_enable_job)) EnableWindow(hwnd, FALSE);
if (hwnd = _hCtrl(btn_browse)) EnableWindow(hwnd, FALSE); if (hwnd = _hCtrl(btn_browse)) ShowWindow(hwnd, SW_HIDE); if (hwnd = _hCtrl(btn_passwd)) EnableWindow(hwnd, FALSE); if (hwnd = _hCtrl(btn_passwd)) ShowWindow(hwnd, SW_HIDE); }
//+--------------------------------------------------------------------------
//
// Function: GetDefaultDomainAndUserName
//
// Synopsis: Fill [pwszDomainAndUserName] with "domain\user" string
//
// Arguments: [pwszDomainAndUserName] - buffer to receive string
// [cchBuf] - should be at least MAX_USERNAME
//
// Modifies: *[pwszDomainAndUserName].
//
// History: 06-03-1997 DavidMun Created
// 2001-11-13 ShBrown Modified to use wchar rather than tchar
//
// Notes: If an error occurs while retrieving the domain name, only
// the user name is returned. If even that cannot be
// retrieved, the buffer is set to an empty string.
//
//---------------------------------------------------------------------------
VOID GetDefaultDomainAndUserName( LPWSTR pwszDomainAndUserName, ULONG cchBuf) { TRACE_FUNCTION(GetDefaultDomainAndUserName);
if (!GetUserNameExW(NameSamCompatible, pwszDomainAndUserName, &cchBuf)) { DEBUG_OUT((DEB_ERROR, "GetDefaultDomainAndUserName: GetUserNameExW failed %d\n", GetLastError()));
pwszDomainAndUserName[0] = L'\0'; } }
void CGeneralPage::_UpdateAppIcon( LPCTSTR ptszAppName) { if (m_updateIcon == 0) { return; }
m_updateIcon = 0;
if (ptszAppName) { m_pIconHelper->SetAppIcon((LPTSTR)ptszAppName); }
BOOL fEnabled;
if (this->IsTaskInTasksFolder()) { fEnabled = (IsDlgButtonChecked(m_hPage, chk_enable_job) == BST_CHECKED); } else { fEnabled = FALSE; }
m_pIconHelper->SetJobIcon(fEnabled);
SendDlgItemMessage(Hwnd(), idc_icon, STM_SETICON, (WPARAM)m_pIconHelper->hiconJob, 0L); }
BOOL CGeneralPage::_Browse( TCHAR szFilePath[]) // of size MAX_PATH
{ TCHAR szDefExt[5]; TCHAR szBrowserDir[MAX_PATH]; TCHAR szFilters[MAX_PATH]; TCHAR szTitle[100];
DWORD dwFlags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
LoadString(g_hInstance, IDS_EXE, szDefExt, ARRAYLEN(szDefExt)); LoadString(g_hInstance, IDS_BROWSE, szTitle, ARRAYLEN(szTitle));
SecureZeroMemory(szFilters, sizeof(szFilters)); if (!LoadString(g_hInstance, IDS_PROGRAMSFILTER, szFilters, ARRAYLEN(szFilters))) { CHECK_HRESULT( HRESULT_FROM_WIN32(GetLastError()) ); return FALSE; }
GetCurrentDirectory(MAX_PATH, szBrowserDir);
OPENFILENAME ofn; SecureZeroMemory(&ofn, sizeof(ofn));
szFilePath[0] = TEXT('\0');
// Setup info for comm dialog.
ofn.lStructSize = CDSIZEOF_STRUCT(OPENFILENAME, lpTemplateName); ofn.hwndOwner = Hwnd(); ofn.hInstance = g_hInstance; ofn.lpstrFilter = szFilters; ofn.nFilterIndex = 1; ofn.lpstrFile = szFilePath; ofn.nMaxFile = MAX_PATH; ofn.lpstrInitialDir = szBrowserDir; ofn.lpstrTitle = szTitle; ofn.Flags = dwFlags; ofn.lpstrDefExt = szDefExt;
// Call it.
if (GetOpenFileName(&ofn) == FALSE) { DEBUG_OUT((DEB_ERROR, "GetOpenFileName failed<0x%x>\n", CommDlgExtendedError()));
return FALSE; } return TRUE; }
LRESULT CGeneralPage::_OnCommand( int id, HWND hwndCtl, UINT codeNotify) { TRACE(CGeneralPage, _OnCommand);
if ((id == btn_browse) && (codeNotify == BN_CLICKED)) { // popup the file browse dialog
TCHAR tszFilePath[MAX_PATH+1];
if (_Browse(tszFilePath)) { if (_tcschr(tszFilePath, TEXT(' '))) { AddQuotes(tszFilePath, MAX_PATH); } SetDlgItemText(Hwnd(), txt_app_name, tszFilePath); SendMessage(Hwnd(), WM_NEXTDLGCTL, (WPARAM)_hCtrl(txt_workingdir), TRUE); _UpdateAppIcon(tszFilePath); _EnableApplyButton(); } } else if (id == btn_passwd && codeNotify == BN_CLICKED) { // popup the set password dialog
LaunchSetPasswordDlg(Hwnd(), &m_AccountInfo);
//
// Since we've launched the set password dialog, we want
// to suppress the set account information dialog which
// otherwise may come up on apply.
//
m_fSuppressAcctInfoRequestOnApply = TRUE;
_EnableApplyButton(); } else if (codeNotify == EN_CHANGE) { switch (id) { case txt_comments: m_CommentDirty = 1; break;
case txt_app_name: //
// If we just did a SetDlgItemText, then this change notification
// should be ignored.
//
if (m_ChangeFromSetText) { m_ChangeFromSetText = 0; } else { m_AppNameDirty = 1; m_updateIcon = 1; } break;
case txt_workingdir: m_WorkingDirDirty = 1; break;
case txt_run_as: //
// If m_fApplyRunAsEditChange is TRUE, the user has edited
// the RunAs control, therefore, we want to apply changes.
// If FALSE, the RunAs control has been automatically updated
// by the UI as a result of an apply. In this case, we do
// not want to apply the change, as it already has been.
//
if (m_fApplyRunAsEditChange) { m_RunAsDirty = 1;
HWND hwnd; if (hwnd = _hCtrl(btn_passwd)) EnableWindow(hwnd, TRUE); break; } else { Win4Assert(!m_fDirty); return TRUE; }
default: return FALSE; }
_EnableApplyButton(); } else if (codeNotify == EN_KILLFOCUS && id == txt_app_name) { if (m_AppNameDirty == 1) { TCHAR tszApp[MAX_PATH + 1];
_GetAppAndArgs(tszApp, MAX_PATH + 1, NULL); if (_JobObjectIsLocal()) { _ExpandAppName(tszApp, MAX_PATH + 1); } _UpdateAppIcon(tszApp); } } else if (id == chk_enable_job) { _EnableApplyButton(); m_updateIcon = 1; _UpdateAppIcon(NULL); }
return TRUE; }
LRESULT CGeneralPage::_OnApply(void) { TRACE(CGeneralPage, _OnApply);
if (m_fDirty == FALSE) { return TRUE; }
HRESULT hr = S_OK; WCHAR wcBuff[MAX_PATH+1]; LPWSTR pwszArg = NULL; BOOL bNoAccountSpecified = FALSE;
do { if (m_CommentDirty == 1) { wcBuff[0] = L'\0';
I_GetDlgItemText(Hwnd(), txt_comments, wcBuff, MAX_PATH+1);
hr = m_pIJob->SetComment(wcBuff);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
m_CommentDirty = 0; }
m_fTaskApplicationChange = FALSE;
if (m_AppNameDirty == 1) { WCHAR wszApp[MAX_PATH + 1];
_UpdateAppNameAndIcon(wszApp, MAX_PATH + 1, &pwszArg); if (pwszArg == NULL) { break; }
hr = m_pIJob->SetApplicationName(wszApp); CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
hr = m_pIJob->SetParameters(pwszArg);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
m_AppNameDirty = 0; m_fTaskApplicationChange = TRUE; }
if (m_WorkingDirDirty == 1) { wcBuff[0] = L'\0';
_ExpandWorkingDir(); I_GetDlgItemText(Hwnd(), txt_workingdir, wcBuff, MAX_PATH+1);
hr = m_pIJob->SetWorkingDirectory(wcBuff);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
m_WorkingDirDirty = 0; }
m_fTaskAccountChange = FALSE; if (m_RunAsDirty == 1 || m_AccountInfo.pwszPassword != tszEmpty) { wcBuff[0] = L'\0'; DWORD ccAccountName = I_GetDlgItemText(Hwnd(), txt_run_as, wcBuff, MAX_USERNAME + 1);
//
// Yell if the user blanked out the field.
//
if (wcBuff[0] == L'\0') { bNoAccountSpecified = TRUE; hr = E_FAIL; break; }
if ((m_RunAsDirty == 1 && m_AccountInfo.pwszAccountName == NULL) || (m_RunAsDirty == 1 && m_AccountInfo.pwszAccountName != NULL && lstrcmpiW(m_AccountInfo.pwszAccountName, wcBuff) != 0)) { //
// The user has changed the account name. Check if they have
// specified a password.
//
if (m_AccountInfo.pwszPassword == tszEmpty) { //
// User hasn't specified a password. Launch the set
// password dialog.
//
LaunchSetPasswordDlg(Hwnd(), &m_AccountInfo);
//
// Since we've launched the set password dialog, we want
// to suppress the set account information dialog which
// otherwise may come up on apply.
//
m_fSuppressAcctInfoRequestOnApply = TRUE; } }
if (m_AccountInfo.pwszPassword != tszEmpty) { //
// Translate input account prior to saving, then save it
//
DWORD cchAccount = MAX_USERNAME + 1; WCHAR wszAccount[MAX_USERNAME + 1] = L""; hr = TranslateAccount(TRANSLATE_FOR_INTERNAL, wcBuff, wszAccount, cchAccount, &(m_AccountInfo.pwszPassword)); if (SUCCEEDED(hr)) { hr = m_pIJob->SetAccountInformation(wszAccount, m_AccountInfo.pwszPassword); }
if (FAILED(hr)) { CHECK_HRESULT(hr); break; }
m_RunAsDirty = 0; m_AccountInfo.fDirty = FALSE; m_fTaskAccountChange = TRUE; } }
//
// Save the job enabled state
//
if (this->IsTaskInTasksFolder()) { DWORD dwFlags;
hr = m_pIJob->GetFlags(&dwFlags);
BOOL fTemp = (IsDlgButtonChecked(m_hPage, chk_enable_job) == BST_CHECKED);
if (m_fEnableJob != fTemp) { m_fEnableJob = fTemp;
if (m_fEnableJob == TRUE) { dwFlags &= ~TASK_FLAG_DISABLED; } else { dwFlags |= TASK_FLAG_DISABLED; }
hr = m_pIJob->SetFlags(dwFlags);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr); } }
//
// reset dirty flag
//
m_fDirty = FALSE;
//
// If evrything went well see if the other pages are ready to
// save the job to storage.
//
if ((m_fPersistChanges == TRUE) && (PropSheet_QuerySiblings(GetParent(Hwnd()), QUERY_READY_TO_BE_SAVED, 0)) == 0) { //
// Save the job file to storage.
//
// For the first release of the scheduling agent, all security
// operations are disabled under Win95, even Win95 to NT.
//
hr = JFSaveJob(Hwnd(), m_pIJob, this->GetPlatformId() == VER_PLATFORM_WIN32_NT && this->IsTaskInTasksFolder(), m_fTaskAccountChange, m_fTaskApplicationChange, m_fSuppressAcctInfoRequestOnApply);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
m_fTaskApplicationChange = FALSE; m_fTaskAccountChange = FALSE; m_fSuppressAcctInfoRequestOnApply = FALSE;
// Will result in refresh of the run as edit control.
//
_UpdateRunAsControl(); }
} while (0);
delete [] pwszArg;
if (FAILED(hr)) { if (hr == E_OUTOFMEMORY) { _ErrorDialog(IERR_OUT_OF_MEMORY); } else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { _ErrorDialog(IERR_FILE_NOT_FOUND); } else if (hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) { _ErrorDialog(IERR_ACCESS_DENIED); } else if (bNoAccountSpecified) { _ErrorDialog(IERR_ACCOUNTNAME); } else { _ErrorDialog(IERR_INTERNAL_ERROR, hr); } }
return SUCCEEDED(hr); }
//+--------------------------------------------------------------------------
//
// Member: CGeneralPage::_UpdateAppNameAndIcon
//
// Synopsis: Update the application name edit control with an expanded
// path for the app, then update the icon for the new path.
//
// Arguments: [wszApp] - NULL or buffer to receive WCHAR app name
// [appBufSize] - size of buffer in WCHARs
// [ppwszArgs] - NULL or address of pointer to buffer to receive
// WCHAR arguments. Must be deallocated with delete[].
//
// Modifies: *[wszApp], *[ppwszArgs]
//
// History: 1-31-1997 DavidMun Created
//
// Notes: App path is only expanded if job object is local.
//
//---------------------------------------------------------------------------
VOID CGeneralPage::_UpdateAppNameAndIcon( LPWSTR wszApp, size_t appBufSize, LPWSTR * ppwszArgs) { TCHAR tszApp[MAX_PATH + 1]; LPTSTR ptszArgs = NULL;
_GetAppAndArgs(tszApp, MAX_PATH + 1, &ptszArgs); if (ptszArgs == NULL) { return; }
if (_JobObjectIsLocal()) { _ExpandAppName(tszApp, MAX_PATH + 1);
m_updateIcon = 1; _UpdateAppIcon(tszApp);
//
// If the working directory is empty and the app is on the local
// machine, provide a default of the directory where the app lives.
//
TCHAR tszWorkingDir[MAX_PATH + 1]; GetDlgItemText(Hwnd(), txt_workingdir, tszWorkingDir, MAX_PATH + 1); StripLeadTrailSpace(tszWorkingDir); DeleteQuotes(tszWorkingDir);
if (!*tszWorkingDir && IsLocalFilename(tszApp)) { StringCchCopy(tszWorkingDir, MAX_PATH + 1, tszApp); DeleteQuotes(tszWorkingDir);
// Get rid of the filename at the end of the string
PathRemoveFileSpec(tszWorkingDir);
if (HasSpaces(tszWorkingDir)) { AddQuotes(tszWorkingDir, MAX_PATH + 1); } SetDlgItemText(Hwnd(), txt_workingdir, tszWorkingDir); }
m_ChangeFromSetText = 1; _SetAppEdit(tszApp, ptszArgs); }
if (wszApp) { StringCchCopy(wszApp, appBufSize, tszApp); }
if (ppwszArgs) { *ppwszArgs = ptszArgs; } else { delete [] ptszArgs; } }
//+--------------------------------------------------------------------------
//
// Member: CGeneralPage::_ExpandWorkingDir
//
// Synopsis: Replace the string in the working directory edit control
// with one which has expanded environment strings.
//
// History: 06-04-1997 DavidMun Created
//
// Notes: Note that this will result in the working dir being marked
// as dirty.
//
//---------------------------------------------------------------------------
VOID CGeneralPage::_ExpandWorkingDir() { TCHAR tszApp[MAX_PATH + 1];
//
// If editing a remote job, don't touch the working dir, since we
// can't expand using its environment variables.
//
if (!_JobObjectIsLocal()) { return; }
TCHAR tszWorkingDir[MAX_PATH + 1];
GetDlgItemText(Hwnd(), txt_workingdir, tszWorkingDir, MAX_PATH + 1); StripLeadTrailSpace(tszWorkingDir); DeleteQuotes(tszWorkingDir);
TCHAR tszExpandedWorkingDir[MAX_PATH + 1];
ULONG cchWritten;
cchWritten = ExpandEnvironmentStrings(tszWorkingDir, tszExpandedWorkingDir, ARRAYLEN(tszExpandedWorkingDir));
//
// If the call succeeded, write the update string to the working dir
// edit control. If there were no environment variables to replace,
// the string will be unchanged.
//
// Note that writing to the edit control will cause an EN_CHANGE which
// will result in m_WorkingDirDirty being set.
//
if (cchWritten && cchWritten <= ARRAYLEN(tszExpandedWorkingDir)) { SetDlgItemText(Hwnd(), txt_workingdir, tszExpandedWorkingDir); } }
//+--------------------------------------------------------------------------
//
// Member: CGeneralPage::_GetAppAndArgs
//
// Synopsis: Fetch the string in the application name edit control and
// split it into the app name part and the arguments part.
//
// Arguments: [tszApp] - NULL or buffer for app name
// [pptszArgs] - NULL or address of pointer to buffer for args,
// must be deallocated with delete[]
//
// Modifies: *[tszApp], *[pptszArgs]
//
// History: 1-31-1997 DavidMun Created
//
// Notes: Application name is space delimited and must be surrounded
// by double quotes if it contains spaces. For example:
//
// text in edit ctrl 'filename' 'arguments'
// --------------------- -------------------------
// notepad.exe foo.txt => 'notepad.exe' 'foo.txt'
// "notepad.exe"foo.txt => '"notepad.exe"foo.txt' ''
// "notepad.exe" foo.txt => '"notepad.exe"' 'foo.txt'
// "no pad.exe" foo.txt => '"no pad.exe"' 'foo.txt'
// no pad.exe foo.txt => 'no' ' pad.exe foo.txt'
//
//---------------------------------------------------------------------------
VOID CGeneralPage::_GetAppAndArgs( LPTSTR tszApp, size_t appBufSize, LPTSTR * pptszArgs) { //
// Split application name into executable name & parameters. First
// strip lead/trail spaces and null terminate at the first whitespace
// outside a quote.
//
int cch = SchedGetDlgItemTextLength(Hwnd(), txt_app_name) + 1; if (cch <= 1) { DEBUG_OUT((DEB_ERROR, "SchedGetDlgItemTextLength failed %d\n", GetLastError())); }
TCHAR *ptszBoth = new TCHAR[cch]; if (ptszBoth == NULL) { DEBUG_OUT((DEB_ERROR, "_GetAppAndArgs alloc failed %d\n", GetLastError())); return; }
GetDlgItemText(Hwnd(), txt_app_name, ptszBoth, cch); StripLeadTrailSpace(ptszBoth);
LPTSTR ptsz; BOOL fInQuote = FALSE;
for (ptsz = ptszBoth; *ptsz; ptsz = NextChar(ptsz)) { if (*ptsz == TEXT('"')) { fInQuote = !fInQuote; } else if (*ptsz == TEXT(' ')) { if (!fInQuote) { *ptsz++ = L'\0'; break; } } }
//
// Return app name if caller wants it.
//
if (tszApp) { StringCchCopy(tszApp, appBufSize, ptszBoth); }
//
// Now ptsz points to the first char past the application
// name. If there are no arguments, then ptsz is pointing
// to the end of the string. Otherwise it's pointing to the
// start of the argument string. Return this if caller wants it.
//
if (pptszArgs) { size_t bufSize = cch - (ptsz - ptszBoth); *pptszArgs = new TCHAR[bufSize]; if (*pptszArgs == NULL) { DEBUG_OUT((DEB_ERROR, "_GetAppAndArgs second alloc failed %d\n", GetLastError())); } else { StringCchCopy(*pptszArgs, bufSize, ptsz); } }
delete [] ptszBoth; }
//+--------------------------------------------------------------------------
//
// Member: CGeneralPage::_ExpandAppName
//
// Synopsis: Change filename in [tszApp] to full path.
//
// Arguments: [tszApp] - filename to modify
//
// Modifies: *[tszApp]
//
// History: 1-31-1997 DavidMun Created
//
// Notes: CAUTION: Should be called only for job objects on the
// LOCAL MACHINE.
//
//---------------------------------------------------------------------------
VOID CGeneralPage::_ExpandAppName( LPTSTR tszApp, size_t cchBuff) { TCHAR tszWorkingDir[MAX_PATH + 1]; BOOL fFound;
GetDlgItemText(Hwnd(), txt_workingdir, tszWorkingDir, MAX_PATH + 1); fFound = ProcessApplicationName(tszApp, cchBuff, tszWorkingDir);
if (_tcschr(tszApp, TEXT(' '))) { AddQuotes(tszApp, MAX_PATH); } }
//+--------------------------------------------------------------------------
//
// Member: CGeneralPage::_SetAppEdit
//
// Synopsis: Set the application edit control to contain the concatenated
// text in [tszApp] and [tszArgs].
//
// Arguments: [tszApp] - application name
// [tszArgs] - arguments
//
// History: 1-31-1997 DavidMun Created
//
// Notes: No modification (adding quotes, etc.) is done to [tszApp].
// Caller should set m_ChangeFromSetText = 1 if calling from
// outside of wm_initdialog processing.
//
//---------------------------------------------------------------------------
VOID CGeneralPage::_SetAppEdit(LPCTSTR tszApp, LPCTSTR tszArgs) { HWND hwndAppName = GetDlgItem(Hwnd(), txt_app_name);
Edit_SetText(hwndAppName, tszApp);
if (tszArgs && *tszArgs) { ULONG cchApp = lstrlen(tszApp);
Edit_SetSel(hwndAppName, cchApp, cchApp); Edit_ReplaceSel(hwndAppName, TEXT(" ")); Edit_SetSel(hwndAppName, cchApp + 1, cchApp + 1); Edit_ReplaceSel(hwndAppName, tszArgs); } }
LRESULT CGeneralPage::_OnCancel(void) { return 0; }
LRESULT CGeneralPage::_OnPSMQuerySibling( WPARAM wParam, LPARAM lParam) { TRACE(CGeneralPage, _OnPSMQuerySibling);
INT_PTR iRet = 0;
switch (wParam) { case QUERY_READY_TO_BE_SAVED: iRet = (int)m_fDirty; break;
case GET_ICON_HELPER: iRet = (INT_PTR)m_pIconHelper; break;
case QUERY_TASK_APPLICATION_DIRTY_STATUS: *((BOOL *)lParam) = m_fTaskApplicationChange; iRet = 1; break;
case QUERY_TASK_ACCOUNT_INFO_DIRTY_STATUS: *((BOOL *)lParam) = m_fTaskAccountChange; iRet = 1; break;
case QUERY_SUPPRESS_ACCOUNT_INFO_REQUEST_FLAG: *((BOOL *)lParam) = m_fSuppressAcctInfoRequestOnApply; iRet = 1; break;
case RESET_TASK_APPLICATION_DIRTY_STATUS: m_fTaskApplicationChange = FALSE; iRet = 1; break;
case RESET_TASK_ACCOUNT_INFO_DIRTY_STATUS: m_fTaskAccountChange = FALSE; iRet = 1; break;
case RESET_SUPPRESS_ACCOUNT_INFO_REQUEST_FLAG: m_fSuppressAcctInfoRequestOnApply = FALSE; iRet = 1; break;
case TASK_ACCOUNT_CHANGE_NOTIFY: Win4Assert(!m_fDirty); _UpdateRunAsControl(); iRet = 1; break;
}
SetWindowLongPtr(Hwnd(), DWLP_MSGRESULT, iRet); return iRet; }
void CGeneralPage::_UpdateRunAsControl(void) { LPWSTR pwsz;
if (SUCCEEDED(m_pIJob->GetAccountInformation(&pwsz))) { //
// Instruct the EN_CHANGE processing of the RunAs edit control
// to not apply this change.
//
m_fApplyRunAsEditChange = FALSE; I_SetDlgItemText(Hwnd(), txt_run_as, pwsz); m_fApplyRunAsEditChange = TRUE; CoTaskMemFree(pwsz); } }
LRESULT CGeneralPage::_OnPSNKillActive( LPARAM lParam) { TRACE(CGeneralPage, _OnPSNKillActive);
if (m_AppNameDirty) { _UpdateAppNameAndIcon(NULL, 0, NULL); }
if (m_WorkingDirDirty) { _ExpandWorkingDir(); } return CPropPage::_OnPSNKillActive(lParam); }
LRESULT CGeneralPage::_OnHelp( HANDLE hRequesting, UINT uiHelpCommand) { WinHelp((HWND)hRequesting, szMstaskHelp, uiHelpCommand, (DWORD_PTR)(LPSTR)s_aGeneralPageHelpIds); return TRUE; }
HRESULT GetGeneralPage( ITask * pIJob, LPTSTR ptszTaskPath, BOOL fPersistChanges, HPROPSHEETPAGE * phpage) { TRACE_FUNCTION(GetGeneralPage);
Win4Assert(pIJob != NULL); Win4Assert(phpage != NULL);
HRESULT hr = S_OK; LPOLESTR polestr = NULL; IPersistFile * ppf = NULL; LPTSTR ptszPath = NULL;
do { //
// Get the job name.
//
if (ptszTaskPath != NULL) { //
// use passed-in path
//
ptszPath = ptszTaskPath; } else { //
// Obtain the job path from the interfaces.
//
hr = GetJobPath(pIJob, &ptszPath); }
BREAK_ON_FAIL(hr);
CGeneralPage * pPage = new CGeneralPage( pIJob, ptszPath, fPersistChanges);
if (pPage == NULL) { hr = E_OUTOFMEMORY; CHECK_HRESULT(hr); break; }
HPROPSHEETPAGE hpage = CreatePropertySheetPage(&pPage->m_psp);
if (hpage == NULL) { delete pPage; hr = E_OUTOFMEMORY; CHECK_HRESULT(hr); break; }
*phpage = hpage;
} while (0);
//
// If we made a copy of pIJob's path string, free it.
//
if (ptszPath != ptszTaskPath) { delete [] ptszPath; }
if (ppf != NULL) { ppf->Release(); }
return hr; }
HRESULT AddGeneralPage( PROPSHEETHEADER &psh, ITask * pIJob) { TRACE_FUNCTION(AddGeneralPage);
HPROPSHEETPAGE hpage = NULL;
HRESULT hr = GetGeneralPage(pIJob, NULL, TRUE, &hpage);
if (SUCCEEDED(hr)) { psh.phpage[psh.nPages++] = hpage; }
return hr; }
HRESULT AddGeneralPage( LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM cookie, ITask * pIJob) { HPROPSHEETPAGE hpage = NULL;
HRESULT hr = GetGeneralPage(pIJob, NULL, TRUE, &hpage);
if (SUCCEEDED(hr)) { if (!lpfnAddPage(hpage, cookie)) { DestroyPropertySheetPage(hpage);
hr = E_FAIL; CHECK_HRESULT(hr); } }
return hr; }
//+---------------------------------------------------------------------------
//
// Function: ResetAccountInfo
//
// Synopsis: Deallocate and initialize the account information specified.
//
// Arguments: [pAccountInfo] -- Account info structure.
//
// Returns: None.
//
// Notes: None.
//
//----------------------------------------------------------------------------
void ResetAccountInfo( AccountInfo * pAccountInfo) { //
// Delete the account name.
//
if (pAccountInfo->pwszAccountName != NULL) { //
// NB : pwszAccountName always allocated by CoTaskMemAlloc.
//
CoTaskMemFree(pAccountInfo->pwszAccountName); pAccountInfo->pwszAccountName = NULL; }
//
// Zero, delete the password. Except when the password is set to the
// static empty string.
//
if (pAccountInfo->pwszPassword != NULL && pAccountInfo->pwszPassword != tszEmpty) { ZERO_PASSWORD(pAccountInfo->pwszPassword); delete pAccountInfo->pwszPassword; pAccountInfo->pwszPassword = (LPWSTR) tszEmpty; } }
//+---------------------------------------------------------------------------
//
// Function: InitializeAccountInfo
//
// Synopsis: Initializes account info fields.
//
// Arguments: [pAccountInfo] -- Account info structure.
//
// Returns: None.
//
// Notes: None.
//
//----------------------------------------------------------------------------
void InitializeAccountInfo(AccountInfo * pAccountInfo) { pAccountInfo->pwszAccountName = NULL;
//
// If we haven't prompted for a password, pwszPassword points to the
// global empty string variable. This allows us to tell whether the
// user intended the password to be an empty string, or we simply
// haven't prompted for it.
//
pAccountInfo->pwszPassword = (LPWSTR) tszEmpty; }
//
// Helpers to launch Set/Change Password & Set Account Information dialogs.
//
//+---------------------------------------------------------------------------
//
// Function: LaunchSetPasswordDlg
//
// Synopsis: Helper to launch the dialog to modify the account password.
//
// Arguments: [hWnd] -- Parent window handle.
// [pAccountInfo] -- Structure manipulated by the dialog.
//
// Returns: DialogBoxParam return code.
//
// Notes: None.
//
//----------------------------------------------------------------------------
INT_PTR LaunchSetPasswordDlg(HWND hWnd, AccountInfo * pAccountInfo) { return(DialogBoxParam(g_hInstance, MAKEINTRESOURCE(set_passwd_dlg), hWnd, SetPasswordDlgProc, (LPARAM)pAccountInfo)); } //+---------------------------------------------------------------------------
//
// Function: LaunchSetAccountInformationDlg
//
// Synopsis: Helper to launch the dialog to modify the account namd and
// password.
//
// Arguments: [hWnd] -- Parent window handle.
// [pAccountInfo] -- Structure manipulated by the dialog.
//
// Returns: DialogBoxParam return code.
//
// Notes: None.
//
//----------------------------------------------------------------------------
INT_PTR LaunchSetAccountInformationDlg(HWND hWnd, AccountInfo * pAccountInfo) { return(DialogBoxParam(g_hInstance, MAKEINTRESOURCE(set_account_info_dlg), hWnd, SetAccountInformationDlgProc, (LPARAM)pAccountInfo)); }
//
// Set/Change Password & Set Account Information dialogs.
//
//+---------------------------------------------------------------------------
//
// Function: SetPasswordDlgProc
//
// Synopsis: This dialog allows the user specify an account password.
// The password is confirmed by a redundant confirmation edit
// field.
//
// Arguments: [hDlg] -- Dialog handle.
// [uMsg] -- Message.
// [wParam] -- Command.
// [lParam] -- Account information dialog ptr on WM_INITDIALOG.
//
// Returns: TRUE -- Message processed by this dialog.
// FALSE -- Message not processed (WM_INITDIALOG excepted).
//
// Notes: None.
//
//----------------------------------------------------------------------------
INT_PTR APIENTRY SetPasswordDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { static AccountInfo * pai = NULL; TCHAR tszPassword[MAX_PASSWORD + 1] = TEXT(""); TCHAR tszConfirmedPassword[MAX_PASSWORD + 1] = TEXT(""); LPWSTR pwszPassword;
switch (uMsg) { case WM_INITDIALOG: Win4Assert(lParam != NULL); pai = (AccountInfo *)lParam; Edit_LimitText(GetDlgItem(hDlg, edt_sp_passwd), MAX_PASSWORD); Edit_LimitText(GetDlgItem(hDlg, edt_sp_cfrmpasswd), MAX_PASSWORD); I_SetDlgItemText(hDlg, edt_sp_passwd, pai->pwszPassword); I_SetDlgItemText(hDlg, edt_sp_cfrmpasswd, pai->pwszPassword);
//
// Center the dialog.
//
CenterDialog(hDlg); return TRUE; // TRUE == let windows set focus
case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: DWORD ccPassword;
ccPassword = GetDlgItemText(hDlg, edt_sp_passwd, tszPassword, MAX_PASSWORD + 1);
GetDlgItemText(hDlg, edt_sp_cfrmpasswd, tszConfirmedPassword, MAX_PASSWORD + 1);
if (lstrcmp(tszPassword, tszConfirmedPassword) != 0) { //
// Passwords didn't match. Let the user know so he/she
// can correct it.
//
SecureZeroMemory(tszPassword, sizeof tszPassword); SecureZeroMemory(tszConfirmedPassword, sizeof tszConfirmedPassword); SchedUIErrorDialog(hDlg, IERR_PASSWORD, (LPTSTR)NULL); return(TRUE); }
if (ccPassword) { //
// Non-NULL password.
//
ccPassword++; pwszPassword = new WCHAR[ccPassword];
if (pwszPassword != NULL) { StringCchCopy(pwszPassword, ccPassword, tszPassword); SecureZeroMemory(tszPassword, sizeof tszPassword); SecureZeroMemory(tszConfirmedPassword, sizeof tszConfirmedPassword); } else { SchedUIErrorDialog(hDlg, IERR_OUT_OF_MEMORY, (LPTSTR)NULL); } } else { //
// Clear the password.
//
pwszPassword = new WCHAR[1]; if (pwszPassword != NULL) { *pwszPassword = L'\0'; } else { SchedUIErrorDialog(hDlg, IERR_OUT_OF_MEMORY, (LPTSTR)NULL); EndDialog(hDlg, wParam); return(TRUE); } }
//
// Zero, delete the previous password. But don't delete the
// static empty string.
//
if (pai->pwszPassword != NULL && pai->pwszPassword != tszEmpty) { ZERO_PASSWORD(pai->pwszPassword); delete pai->pwszPassword; } pai->pwszPassword = pwszPassword;
case IDCANCEL: SecureZeroMemory(tszPassword, sizeof tszPassword); SecureZeroMemory(tszConfirmedPassword, sizeof tszConfirmedPassword); EndDialog(hDlg, wParam); return TRUE;
default: return FALSE; }
case WM_HELP: WinHelp((HWND) ((LPHELPINFO) lParam)->hItemHandle, szMstaskHelp, HELP_WM_HELP, (DWORD_PTR)(LPSTR)s_aSetPasswordDlgHelpIds); return TRUE;
case WM_CONTEXTMENU: WinHelp((HWND) wParam, szMstaskHelp, HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)s_aSetPasswordDlgHelpIds); return TRUE;
default: return FALSE; } }
//+---------------------------------------------------------------------------
//
// Function: SetAccountInformationDlgProc
//
// Synopsis: This dialog allows the user to specify full account
// information: the account name and password. The password
// is confirmed by a redundant confirmation edit field.
// Logic also ensures the user must specify an account name.
//
// Arguments: [hDlg] -- Dialog handle.
// [uMsg] -- Message.
// [wParam] -- Command.
// [lParam] -- Account information dialog ptr on WM_INITDIALOG.
//
// Returns: TRUE -- Message processed by this dialog.
// FALSE -- Message not processed (WM_INITDIALOG excepted).
//
// Notes: None.
//
//----------------------------------------------------------------------------
INT_PTR APIENTRY SetAccountInformationDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { static AccountInfo * pai = NULL; TCHAR tszAccountName[MAX_USERNAME + 1] = TEXT(""); TCHAR tszPassword[MAX_PASSWORD + 1] = TEXT(""); TCHAR tszConfirmedPassword[MAX_PASSWORD + 1] = TEXT(""); DWORD ccAccountName = MAX_USERNAME + 1; LPWSTR pwszPassword;
switch (uMsg) { case WM_INITDIALOG: Win4Assert(lParam != NULL); pai = (AccountInfo *)lParam; Edit_LimitText(GetDlgItem(hDlg, edt_sa_passwd), MAX_USERNAME); Edit_LimitText(GetDlgItem(hDlg, edt_sa_passwd), MAX_PASSWORD); Edit_LimitText(GetDlgItem(hDlg, edt_sa_cfrmpasswd), MAX_PASSWORD); if (pai->pwszAccountName != NULL) { //
// Translate account prior to display, then display it
//
HRESULT hr = TranslateAccount(TRANSLATE_FOR_DISPLAY, pai->pwszAccountName, tszAccountName, ccAccountName); if (FAILED(hr)) { StringCchCopy(tszAccountName, MAX_USERNAME + 1, pai->pwszAccountName); } } else { GetDefaultDomainAndUserName(tszAccountName, ccAccountName); } SetDlgItemText(hDlg, txt_sa_run_as, tszAccountName); I_SetDlgItemText(hDlg, edt_sa_passwd, pai->pwszPassword); I_SetDlgItemText(hDlg, edt_sa_cfrmpasswd, pai->pwszPassword);
//
// Center the dialog.
//
CenterDialog(hDlg); return TRUE; // TRUE == let windows set focus
case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: DWORD ccAccountName, ccPassword; tszAccountName[0] = _T('\0');
ccAccountName = GetDlgItemText(hDlg, txt_sa_run_as, tszAccountName, MAX_USERNAME + 1);
if (tszAccountName[0] != _T('\0')) { ccAccountName++; LPWSTR pwszAccountName = (LPWSTR)CoTaskMemAlloc( ccAccountName * sizeof(WCHAR));
if (pwszAccountName != NULL) { StringCchCopy(pwszAccountName, ccAccountName, tszAccountName);
ccPassword = GetDlgItemText(hDlg, edt_sa_passwd, tszPassword, MAX_PASSWORD + 1);
GetDlgItemText(hDlg, edt_sa_cfrmpasswd, tszConfirmedPassword, MAX_PASSWORD + 1);
if (lstrcmp(tszPassword, tszConfirmedPassword) != 0) { //
// Passwords didn't match. Let the user know so he/she
// can correct it.
//
CoTaskMemFree(pwszAccountName); SchedUIErrorDialog(hDlg, IERR_PASSWORD, (LPTSTR)NULL); return(TRUE); } else { if (ccPassword) { //
// Non-NULL password.
//
ccPassword++; pwszPassword = new WCHAR[ccPassword];
if (pwszPassword != NULL) { StringCchCopy(pwszPassword, ccPassword, tszPassword); SecureZeroMemory(tszPassword, sizeof tszPassword); SecureZeroMemory(tszConfirmedPassword, sizeof tszConfirmedPassword); } else { CoTaskMemFree(pwszAccountName); SchedUIErrorDialog(hDlg, IERR_OUT_OF_MEMORY, (LPTSTR)NULL); EndDialog(hDlg, wParam); return(TRUE); } } else { //
// Clear the password.
//
pwszPassword = new WCHAR[1]; if (pwszPassword != NULL) { *pwszPassword = L'\0'; } else { CoTaskMemFree(pwszAccountName); SchedUIErrorDialog(hDlg, IERR_OUT_OF_MEMORY, (LPTSTR)NULL); EndDialog(hDlg, wParam); return(TRUE); } } }
if (pai->pwszAccountName != NULL) { CoTaskMemFree(pai->pwszAccountName); pai->pwszAccountName = NULL; } if (pai->pwszPassword != NULL && pai->pwszPassword != tszEmpty) { ZERO_PASSWORD(pai->pwszPassword); delete pai->pwszPassword; pai->pwszPassword = NULL; }
//
// Translate input account prior to saving, then save it
//
DWORD cchAccount = MAX_USERNAME + 1; WCHAR wszAccount[MAX_USERNAME + 1] = L""; HRESULT hr = TranslateAccount(TRANSLATE_FOR_INTERNAL, pwszAccountName, wszAccount, cchAccount, &pwszPassword); if (SUCCEEDED(hr)) { lstrcpynW(pwszAccountName, wszAccount, cchAccount); // copy translated name back into original buffer which will evenutally be CoTaskMemFree'd
pai->pwszAccountName = pwszAccountName; pai->pwszPassword = pwszPassword; } else { CoTaskMemFree(pwszAccountName); SchedUIErrorDialog(hDlg, IERR_INTERNAL_ERROR, (LPTSTR)NULL); EndDialog(hDlg, wParam); return(TRUE); } } else { SchedUIErrorDialog(hDlg, IERR_OUT_OF_MEMORY, (LPTSTR)NULL); EndDialog(hDlg, wParam); return(TRUE); } } else { //
// User cannot specify an empty account name.
//
SchedUIErrorDialog(hDlg, IERR_ACCOUNTNAME, (LPTSTR)NULL); return(TRUE); }
case IDCANCEL: EndDialog(hDlg, wParam); return TRUE; }
default: return FALSE; } }
//+---------------------------------------------------------------------------
//
// Function: CenterDialog
//
// Synopsis: Helper to center a dialog on screen.
//
// Arguments: [hDlg] -- Dialog handle.
//
// Returns: None.
//
// Notes: None.
//
//----------------------------------------------------------------------------
void CenterDialog(HWND hDlg) { RECT rc; GetWindowRect(hDlg, &rc);
SetWindowPos(hDlg, NULL, ((GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) / 2), ((GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) / 2), 0, 0, SWP_NOSIZE | SWP_NOACTIVATE); }
//+---------------------------------------------------------------------------
//
// Function: SchedGetDlgItemTextLength
//
// Synopsis: Implements a GetDlgItemTextLength function since Win32 lacks it
//
// Arguments:
//
// Returns:
//
//----------------------------------------------------------------------------
int SchedGetDlgItemTextLength( HWND hwnd, int id) { if ((hwnd = GetDlgItem(hwnd, id)) != NULL) { return GetWindowTextLength(hwnd); }
return 0; }
|