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
2350 lines
66 KiB
//____________________________________________________________________________
|
|
//
|
|
// 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;
|
|
}
|
|
|