//____________________________________________________________________________ // // 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" #if !defined(_CHICAGO_) #define SECURITY_WIN32 #include // GetUserNameEx #undef SECURITY_WIN32 #include "..\inc\network.hxx" #endif // !defined(_CHICAGO_) #include "rc.h" #include "defines.h" #include #include "uiutil.hxx" #include "commdlg.h" #include "helpids.h" #include "iconhlpr.hxx" #include "schedui.hxx" #include "sageset.hxx" // // extern // extern HINSTANCE g_hInstance; #if !defined(_CHICAGO_) // // 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); #endif // !defined(_CHICAGO_) 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); VOID _ExpandWorkingDir(); VOID _GetAppAndArgs(LPTSTR tszApp, LPTSTR * pptszArg); VOID _UpdateAppNameAndIcon(LPWSTR wszApp, LPWSTR * ppwszArg); VOID _UpdateAppIcon(LPCTSTR tszApp); VOID _SetAppEdit(LPCTSTR tszApp, LPCTSTR tszArgs); BOOL _JobObjectIsLocal(); #if !defined(_CHICAGO_) void _UpdateRunAsControl(void); #endif // !defined(_CHICAGO_) BOOL _Browse(TCHAR szFilePath[]); void _ErrorDialog(int idsErr, LONG error = 0, UINT idsHelpHint = 0) { SchedUIErrorDialog(Hwnd(), idsErr, error, idsHelpHint); } #if !defined(_CHICAGO_) AccountInfo m_AccountInfo; // Account/password change info. #endif // !defined(_CHICAGO_) 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; // // Should we save on Apply or OK. // BOOL m_fPersistChanges; BOOL m_fEnableJob; // // Saved or new sage settings parameter // TCHAR m_tszSageRunParam[20]; // /SAGERUN:4294967295 #if !defined(_CHICAGO_) // // 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; #endif // !defined(_CHICAGO_) }; // class CGeneralPage inline CGeneralPage::CGeneralPage( ITask * pIJob, LPTSTR ptszTaskPath, BOOL fPersistChanges) : m_pIJob(pIJob), m_pIconHelper(NULL), m_fPersistChanges(fPersistChanges), m_ChangeFromSetText(FALSE), #if !defined(_CHICAGO_) m_fApplyRunAsEditChange(TRUE), m_fTaskApplicationChange(FALSE), m_fTaskAccountChange(FALSE), m_fSuppressAcctInfoRequestOnApply(FALSE), #endif // !defined(_CHICAGO_) CPropPage(MAKEINTRESOURCE(general_page), ptszTaskPath) { TRACE(CGeneralPage, CGeneralPage); Win4Assert(m_pIJob != NULL); m_pIJob->AddRef(); m_tszSageRunParam[0] = TEXT('\0'); #if !defined(_CHICAGO_) InitializeAccountInfo(&m_AccountInfo); #endif // !defined(_CHICAGO_) } inline CGeneralPage::~CGeneralPage() { TRACE(CGeneralPage, ~CGeneralPage); if (m_pIconHelper != NULL) { m_pIconHelper->Release(); } if (m_pIJob != NULL) { m_pIJob->Release(); } #if !defined(_CHICAGO_) ResetAccountInfo(&m_AccountInfo); #endif // !defined(_CHICAGO_) } //+-------------------------------------------------------------------------- // // 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. // Edit_LimitText(_hCtrl(txt_comments), MAX_PATH); Edit_LimitText(_hCtrl(txt_workingdir), MAX_PATH); Edit_LimitText(_hCtrl(txt_run_as), 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")); EnableWindow(_hCtrl(btn_browse), FALSE); ShowWindow(_hCtrl(btn_browse), SW_HIDE); EnableWindow(_hCtrl(txt_app_name), FALSE); EnableWindow(_hCtrl(txt_workingdir), FALSE); } do { #if !defined(_CHICAGO_) // // NB : For the first release of the scheduling agent, all security // operations are disabled under Win95, even Win95 to NT. // // // 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()); #else fEnableSecurity = FALSE; #endif // !defined(_CHICAGO_) if (!fEnableSecurity) { DestroyWindow(_hCtrl(lbl_run_as)); DestroyWindow(_hCtrl(txt_run_as)); DestroyWindow(_hCtrl(btn_passwd)); } // 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); #if defined(_CHICAGO_) // // Show the settings button only on Win95 and only if the task's // application is Sage-aware. Using the ApplicationName property in // pwsz, before it is freed below. // hr = UnicodeToAnsi(tszApp, pwsz, MAX_PATH+1); if (SUCCEEDED(hr) && !IsSageAware(tszApp, NULL, NULL)) { // // The app isn't Sage-aware, so hide the Settings button and // move the Browse button to the Settings button position. // HWND hBrowseBtn = GetDlgItem(Hwnd(), btn_browse); HWND hSettingsBtn = GetDlgItem(Hwnd(), btn_settings); WINDOWPLACEMENT wp; wp.length = sizeof(WINDOWPLACEMENT); GetWindowPlacement(hSettingsBtn, &wp); ShowWindow(hSettingsBtn, SW_HIDE); MoveWindow(hBrowseBtn, wp.rcNormalPosition.left, wp.rcNormalPosition.top, wp.rcNormalPosition.right - wp.rcNormalPosition.left, wp.rcNormalPosition.bottom - wp.rcNormalPosition.top, FALSE); } #else lstrcpyn(tszApp, pwsz, MAX_PATH + 1); #endif // defined(_CHICAGO_) // // 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); #if !defined(UNICODE) TCHAR tszArg[MAX_PATH + 1]; UnicodeToAnsi(tszArg, pwsz, MAX_PATH + 1); #else TCHAR * tszArg = pwsz; #endif // !defined(UNICODE) // // 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); wcscat(wszWorkingDir, L"\""); I_SetDlgItemText(Hwnd(), txt_workingdir, wszWorkingDir); } else { I_SetDlgItemText(Hwnd(), txt_workingdir, pwsz); } CoTaskMemFree(pwsz); // // 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); if (!this->IsTaskInTasksFolder()) { EnableWindow(_hCtrl(chk_enable_job), FALSE); m_fEnableJob = FALSE; } #if !defined(_CHICAGO_) if (fEnableSecurity) { // // Set account name (run as) // hr = m_pIJob->GetAccountInformation(&pwsz); if (SUCCEEDED(hr)) { I_SetDlgItemText(Hwnd(), txt_run_as, pwsz); m_AccountInfo.pwszAccountName = pwsz; EnableWindow(_hCtrl(btn_passwd), TRUE); } else if (hr == SCHED_E_ACCOUNT_INFORMATION_NOT_SET) { hr = S_OK; // // Set the run as field to the current user's name and // enable the set/change password button. // Leave it blank for AT jobs - else they look like they've // been set to run as this user, which is very confusing // (see bug 376163). BUGBUG Better behavior would be to // display a status message that this is an AT job and will // be upgraded if modified. // TCHAR tszUserName[MAX_USERNAME + 1] = TEXT(""); if (! (dwFlags & JOB_I_FLAG_NET_SCHEDULE)) { GetDefaultDomainAndUserName(tszUserName, MAX_USERNAME + 1); } SetDlgItemText(Hwnd(), txt_run_as, tszUserName); EnableWindow(_hCtrl(btn_passwd), TRUE); } 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); } } #endif // !defined(_CHICAGO_) } while (0); 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; } #if !defined(_CHICAGO_) //+-------------------------------------------------------------------------- // // Function: GetDefaultDomainAndUserName // // Synopsis: Fill [ptszDomainAndUserName] with "domain\user" string // // Arguments: [ptszDomainAndUserName] - buffer to receive string // [cchBuf] - should be at least MAX_USERNAME // // Modifies: *[ptszDomainAndUserName]. // // History: 06-03-1997 DavidMun Created // // 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( LPTSTR ptszDomainAndUserName, ULONG cchBuf) { TRACE_FUNCTION(GetDefaultDomainAndUserName); if (!GetUserNameEx(NameSamCompatible, ptszDomainAndUserName, &cchBuf)) { DEBUG_OUT((DEB_ERROR, "GetDefaultDomainAndUserName: GetUserNameEx failed %d\n", GetLastError())); ptszDomainAndUserName[0] = L'\0'; } } #endif // !defined(_CHICAGO_) 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)); ZeroMemory(szFilters, ARRAYLEN(szFilters)); if (!LoadString(g_hInstance, IDS_PROGRAMSFILTER, szFilters, ARRAYLEN(szFilters))) { CHECK_HRESULT( HRESULT_FROM_WIN32(GetLastError()) ); return FALSE; } GetCurrentDirectory(MAX_PATH, szBrowserDir); OPENFILENAME ofn; ZeroMemory(&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(); } } #if defined(_CHICAGO_) else if (id == btn_settings && codeNotify == BN_CLICKED) { TCHAR tszApp[MAX_PATH + 1]; _GetAppAndArgs(tszApp, NULL); // invoke the application to do its settings. BOOL fHadSageRun = (*m_tszSageRunParam != '\0'); DoSageSettings(tszApp, m_tszSageRunParam); // // If the DoSageSettings func created a /sagerun parameter, // mark the app name as dirty, since the sagerun parameter doesn't // appear in the UI, therefore we won't be doing a settext with // it and automatically dirtying. // if (!fHadSageRun && *m_tszSageRunParam) { m_AppNameDirty = 1; _EnableApplyButton(); } } #endif // defined(_CHICAGO_) #if !defined(_CHICAGO_) 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(); } #endif // !defined(_CHICAGO_) 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 !defined(_CHICAGO_) // // 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; EnableWindow(_hCtrl(btn_passwd), TRUE); break; } else { Win4Assert(!m_fDirty); return TRUE; } #endif // !defined(_CHICAGO_) default: return FALSE; } _EnableApplyButton(); } else if (codeNotify == EN_KILLFOCUS && id == txt_app_name) { if (m_AppNameDirty == 1) { TCHAR tszApp[MAX_PATH + 1]; _GetAppAndArgs(tszApp, NULL); if (_JobObjectIsLocal()) { _ExpandAppName(tszApp); } _UpdateAppIcon(tszApp); } } else if (id == chk_enable_job) { _EnableApplyButton(); m_updateIcon = 1; _UpdateAppIcon(NULL); } return TRUE; } LRESULT CGeneralPage::_OnApply(void) { TRACE(CGeneralPage, _OnApply); //DbxDisplay("CGeneralPage::_OnApply"); if (m_fDirty == FALSE) { return TRUE; } HRESULT hr = S_OK; WCHAR wcBuff[MAX_PATH+1]; LPWSTR pwszArg = NULL; 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; } #if !defined(_CHICAGO_) m_fTaskApplicationChange = FALSE; #endif // !defined(_CHICAGO_) if (m_AppNameDirty == 1) { WCHAR wszApp[MAX_PATH + 1]; _UpdateAppNameAndIcon(wszApp, &pwszArg); if (pwszArg == NULL) { break; } hr = m_pIJob->SetApplicationName(wszApp); CHECK_HRESULT(hr); BREAK_ON_FAIL(hr); // // Since the application name has changed, it may no longer name // (or may now name) a sage-aware application. Make sure that // the sagerun argument is appended only if it should be. // // BUGBUG IsSageAware and CreateSageRunKey use HKLM, so they're // broken for remote case. If this is fixed, enable this code // on NT if the target machine is win9x. // // BUGBUG pwszArg is limited to MAX_PATH characters on Win9x. // #if defined(_CHICAGO_) int iSageRun; if (IsSageAwareW(wszApp, pwszArg, &iSageRun)) { wsprintf(m_tszSageRunParam, TEXT("%s%u"), SAGERUN_PARAM, iSageRun); CHAR szApp[MAX_PATH + 1]; UnicodeToAnsi(szApp, wszApp, ARRAYLEN(szApp)); LPSTR pszFileName = PathFindFileName(szApp); if (pszFileName) { CreateSageRunKey(pszFileName, iSageRun); } } else { *m_tszSageRunParam = TEXT('\0'); } WCHAR wszArg[MAX_PATH + 1]; ULONG cchArg = wcslen(pwszArg); if (*m_tszSageRunParam && lstrlen(m_tszSageRunParam) + cchArg + 1 < ARRAYLEN(wszArg)) { wcscpy(wszArg, pwszArg); if (cchArg) { wszArg[cchArg++] = L' '; } AnsiToUnicode(&wszArg[cchArg], m_tszSageRunParam, ARRAYLEN(wszArg) - cchArg); hr = m_pIJob->SetParameters(wszArg); } else { hr = m_pIJob->SetParameters(pwszArg); } #else hr = m_pIJob->SetParameters(pwszArg); #endif // defined(_CHICAGO_) CHECK_HRESULT(hr); BREAK_ON_FAIL(hr); m_AppNameDirty = 0; #if !defined(_CHICAGO_) m_fTaskApplicationChange = TRUE; #endif // !defined(_CHICAGO_) } 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; } // // For the first release of the scheduling agent, all security // operations are disabled under Win95, even Win95 to NT. // #if !defined(_CHICAGO_) 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); 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) { hr = m_pIJob->SetAccountInformation( wcBuff, m_AccountInfo.pwszPassword); if (FAILED(hr)) { CHECK_HRESULT(hr); break; } m_RunAsDirty = 0; m_AccountInfo.fDirty = FALSE; m_fTaskAccountChange = TRUE; } } #endif // !defined(_CHICAGO_) // // 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, #if !defined(_CHICAGO_) this->GetPlatformId() == VER_PLATFORM_WIN32_NT && this->IsTaskInTasksFolder(), m_fTaskAccountChange, m_fTaskApplicationChange, m_fSuppressAcctInfoRequestOnApply); #else FALSE, FALSE, FALSE, TRUE); #endif // !defined(_CHICAGO_) CHECK_HRESULT(hr); BREAK_ON_FAIL(hr); #if !defined(_CHICAGO_) m_fTaskApplicationChange = FALSE; m_fTaskAccountChange = FALSE; m_fSuppressAcctInfoRequestOnApply = FALSE; // Will result in refresh of the run as edit control. // _UpdateRunAsControl(); #endif // !defined(_CHICAGO_) } } 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 { _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 // [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, LPWSTR * ppwszArgs) { TCHAR tszApp[MAX_PATH + 1]; LPTSTR ptszArgs = NULL; TCHAR tszAppAndArg[MAX_PATH + 1]; _GetAppAndArgs(tszApp, &ptszArgs); if (ptszArgs == NULL) { return; } if (_JobObjectIsLocal()) { _ExpandAppName(tszApp); 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)) { lstrcpy(tszWorkingDir, 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) { #if !defined(UNICODE) AnsiToUnicode(wszApp, tszApp, MAX_PATH + 1); #else lstrcpy(wszApp, tszApp); #endif // defined(UNICODE) } if (ppwszArgs) { #if !defined(UNICODE) LONG cch = lstrlen(ptszArgs) + 1; *ppwszArgs = new WCHAR[cch]; if (*ppwszArgs != NULL) { AnsiToUnicode(*ppwszArgs, ptszArgs, cch); } delete [] ptszArgs; #else *ppwszArgs = ptszArgs; #endif // defined(UNICODE) } 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]; TCHAR tszAppAndArg[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, 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) { lstrcpy(tszApp, 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) { *pptszArgs = new TCHAR[cch - (ptsz - ptszBoth)]; if (*pptszArgs == NULL) { DEBUG_OUT((DEB_ERROR, "_GetAppAndArgs second alloc failed %d\n", GetLastError())); } else { lstrcpy(*pptszArgs, 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) { TCHAR tszWorkingDir[MAX_PATH + 1]; BOOL fFound; GetDlgItemText(Hwnd(), txt_workingdir, tszWorkingDir, MAX_PATH + 1); fFound = ProcessApplicationName(tszApp, 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; #if !defined(_CHICAGO_) 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; #endif // !defined(_CHICAGO_) } SetWindowLongPtr(Hwnd(), DWLP_MSGRESULT, iRet); return iRet; } #if !defined(_CHICAGO_) 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); } } #endif // !defined(_CHICAGO_) LRESULT CGeneralPage::_OnPSNKillActive( LPARAM lParam) { TRACE(CGeneralPage, _OnPSNKillActive); if (m_AppNameDirty) { _UpdateAppNameAndIcon(NULL, 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; } #if !defined(_CHICAGO_) //+--------------------------------------------------------------------------- // // 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; } } #endif // !defined(_CHICAGO_) #if !defined(_CHICAGO_) //+--------------------------------------------------------------------------- // // 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; } #endif // !defined(_CHICAGO_) // // Helpers to launch Set/Change Password & Set Account Information dialogs. // #if !defined(_CHICAGO_) //+--------------------------------------------------------------------------- // // 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)); } #endif // !defined(_CHICAGO_) #if !defined(_CHICAGO_) //+--------------------------------------------------------------------------- // // 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)); } #endif // !defined(_CHICAGO_) // // Set/Change Password & Set Account Information dialogs. // #if !defined(_CHICAGO_) //+--------------------------------------------------------------------------- // // 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. // ZeroMemory(tszPassword, sizeof tszPassword); ZeroMemory(tszConfirmedPassword, sizeof tszConfirmedPassword); SchedUIErrorDialog(hDlg, IERR_PASSWORD, (LPTSTR)NULL); return(TRUE); } if (ccPassword) { // // Non-NULL password. // ccPassword++; pwszPassword = new WCHAR[ccPassword]; if (pwszPassword != NULL) { #if !defined(UNICODE) HRESULT hr = AnsiToUnicode(pwszPassword, tszPassword, ccPassword); if (FAILED(hr)) { SchedUIErrorDialog(hDlg, IERR_INTERNAL_ERROR, 0); ZERO_PASSWORD(pwszPassword); delete [] pwszPassword; ZeroMemory(tszPassword, sizeof tszPassword); ZeroMemory(tszConfirmedPassword, sizeof tszConfirmedPassword); return(TRUE); } #else lstrcpy(pwszPassword, tszPassword); #endif // !defined(UNICODE) } 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: ZeroMemory(tszPassword, sizeof tszPassword); ZeroMemory(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; } } #endif // !defined(_CHICAGO_) #if !defined(_CHICAGO_) //+--------------------------------------------------------------------------- // // 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) { #if !defined(UNICODE) // // Even if conversion fails, tszAccountName will be terminated, // so put it in the UI regardless. // ZeroMemory(tszAccountName, ARRAYLEN(tszAccountName)); (void) UnicodeToAnsi(tszAccountName, pai->pwszAccountName, ccAccountName); #else lstrcpy(tszAccountName, pai->pwszAccountName); #endif // !defined(UNICODE) } 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) { #if !defined(UNICODE) HRESULT hr = AnsiToUnicode(pwszAccountName, tszAccountName, ccAccountName); if (FAILED(hr)) { CoTaskMemFree(pwszAccountName); SchedUIErrorDialog(hDlg, IERR_INTERNAL_ERROR, 0); break; } #else lstrcpy(pwszAccountName, tszAccountName); #endif // !defined(UNICODE) 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) { #if !defined(UNICODE) HRESULT hr = AnsiToUnicode(pwszPassword, tszPassword, ccPassword); if (FAILED(hr)) { CoTaskMemFree(pwszAccountName); SchedUIErrorDialog(hDlg, IERR_INTERNAL_ERROR, 0); return(TRUE); } #else lstrcpy(pwszPassword, tszPassword); #endif // !defined(UNICODE) } 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); } if (pai->pwszPassword != NULL && pai->pwszPassword != tszEmpty) { ZERO_PASSWORD(pai->pwszPassword); delete pai->pwszPassword; } pai->pwszAccountName = pwszAccountName; pai->pwszPassword = pwszPassword; } else { SchedUIErrorDialog(hDlg, IERR_OUT_OF_MEMORY, (LPTSTR)NULL); } } 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; } } #endif // !defined(_CHICAGO_) #if !defined(_CHICAGO_) //+--------------------------------------------------------------------------- // // 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); } #endif // !defined(_CHICAGO_) //+--------------------------------------------------------------------------- // // 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; }