|
|
//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1994 - 1996.
//
// File: taskwiz.cxx
//
// Contents: Class which creates and invokes the 'create new task' wizard.
//
// Classes: CTaskWizard
//
// History: 5-20-1997 DavidMun Created
//
//---------------------------------------------------------------------------
#include "..\pch\headers.hxx"
#pragma hdrstop
#include "myheaders.hxx"
#include "..\folderui\jobidl.hxx"
//
// Types
//
// SFindWiz - passed to window enumeration function. BUGBUG when wizard
// on remote machine is supported, the 'tszFocus' member should be the
// server name. For now, it is just the path to the tasks folder.
//
struct SFindWiz { BOOL fFound; LPCTSTR tszFocus; };
//
// Globals
//
// g_msgFindWizard - private window message used to interrogate the wizard
// dialog proc during the find operation.
//
// TEMPLATE_STR - string used to create private message, also used by
// folderui code to identify the template icon.
//
UINT g_msgFindWizard; extern const TCHAR TEMPLATE_STR[];
//
// External references
//
extern HRESULT QuietStartContinueService(); // ..\folderui\schstate.cxx
extern HRESULT JFGetDataObject( LPCTSTR pszFolderPath, LPCITEMIDLIST pidlFolder, UINT cidl, LPCITEMIDLIST * apidl, BOOL fCut, LPVOID * ppvObj);
extern HRESULT DisplayJobProperties( LPDATAOBJECT pdtobj);
//+--------------------------------------------------------------------------
//
// Member: CTaskWizard::CTaskWizard
//
// Synopsis: ctor
//
// Arguments: [ptszFolderPath] - path to tasks folder
//
// History: 5-12-1997 DavidMun Created
//
//---------------------------------------------------------------------------
CTaskWizard::CTaskWizard( LPCTSTR ptszFolderPath, LPITEMIDLIST pidlFolder) { TRACE_CONSTRUCTOR(CTaskWizard);
SecureZeroMemory(_apWizPages, sizeof _apWizPages); _fAdvanced = FALSE; _tszJobObjectFullPath[0] = TEXT('\0'); _pTask = NULL; lstrcpyn(_tszFolderPath, ptszFolderPath, ARRAYLEN(_tszFolderPath)); _pidlFolder = pidlFolder; #ifdef WIZARD97
_fUse256ColorBmp = Is256ColorSupported(); #endif // WIZARD97
}
//+--------------------------------------------------------------------------
//
// Member: CTaskWizard::~CTaskWizard
//
// Synopsis: dtor
//
// History: 5-19-1997 DavidMun Created
//
//---------------------------------------------------------------------------
CTaskWizard::~CTaskWizard() { TRACE_DESTRUCTOR(CTaskWizard);
if (_pTask) { _pTask->Release(); }
ILFree(_pidlFolder); }
//+--------------------------------------------------------------------------
//
// Member: CTaskWizard::Launch, static
//
// Synopsis: Run the task wizard in a separate thread.
//
// Arguments: [ptszFolderPath] - path to tasks folder.
//
// Returns: HRESULT
//
// History: 5-19-1997 DavidMun Created
//
// Notes: If an instance of the wizard is already running for the
// target machine, makes that the foreground window and
// returns.
//
//---------------------------------------------------------------------------
HRESULT CTaskWizard::Launch( LPCTSTR ptszFolderPath, LPCITEMIDLIST pidlFolder) { TRACE_FUNCTION(CTaskWizard::Launch);
HRESULT hr = S_OK; CTaskWizard *pNewWiz = NULL;
do { //
// Start the service if it isn't running, or continue it if it is
// paused. Since this is the wizard, do it on behalf of the user
// without asking first.
//
// Continue on failure, since it is better to let the user at least
// create the task, even if the service can't be started (user might
// not have permission).
//
hr = QuietStartContinueService(); CHECK_HRESULT(hr);
//
// Create a path string that CPropPage will store. This is the
// full path to the tasks folder, with a trailing backslash. The
// CPropPage will truncate at the last backslash, since most other
// callers give it a task filename.
//
ULONG cchPath = lstrlen(ptszFolderPath);
if (cchPath >= MAX_PATH - 1) // reserve space for trailing backslash
{ hr = E_INVALIDARG; DEBUG_OUT_HRESULT(hr); break; }
TCHAR tszFolderPath[MAX_PATH + 1];
StringCchCopy(tszFolderPath, MAX_PATH + 1, ptszFolderPath); tszFolderPath[cchPath] = TEXT('\\'); tszFolderPath[cchPath + 1] = TEXT('\0');
//
// Look for an instance of the wizard running and focused on our
// folder path. If one is found, it will make itself foreground
// window, and we can quit.
//
hr = _FindWizard(tszFolderPath);
if (hr == S_OK) { break; }
//
// No wizard is up for the current focus. Create a wizard object
// and run it in a new thread.
//
LPITEMIDLIST pidlFolderCopy = ILClone(pidlFolder);
if (!pidlFolderCopy) { hr = E_OUTOFMEMORY; DEBUG_OUT_HRESULT(hr); break; }
pNewWiz = new CTaskWizard(tszFolderPath, pidlFolderCopy);
if (!pNewWiz) { ILFree(pidlFolderCopy); hr = E_OUTOFMEMORY; DEBUG_OUT_HRESULT(hr); break; }
HANDLE hThread; DWORD idThread;
hThread = CreateThread(NULL, 0, _WizardThreadProc, (LPVOID) pNewWiz, 0, &idThread);
if (!hThread) { delete pNewWiz; DEBUG_OUT_LASTERROR; hr = HRESULT_FROM_LASTERROR; break; }
VERIFY(CloseHandle(hThread)); } while (0);
return hr; }
//+--------------------------------------------------------------------------
//
// Member: CTaskWizard::_WizardThreadProc, static
//
// Synopsis: Displays the wizard (and optionally task property sheet)
// using a separate thread.
//
// Arguments: [pvThis] - CTaskWizard pointer
//
// Returns: HRESULT
//
// History: 5-20-1997 DavidMun Created
//
// Notes: The wizard runs in a separate thread so the explorer ui
// isn't stalled.
//
//---------------------------------------------------------------------------
DWORD WINAPI CTaskWizard::_WizardThreadProc( LPVOID pvThis) { HRESULT hr = OleInitialize(NULL);
if (FAILED(hr)) { DEBUG_OUT_HRESULT(hr); return hr; }
CTaskWizard *pThis = (CTaskWizard *)pvThis;
__try { hr = pThis->_DoWizard();
//
// Once _DoWizard returns, the wizard property sheet has closed.
//
// If the user elected to see the new task's property sheet, then
// _fAdvanced will be set, and the completion page should have
// set a valid filename and interface pointer for the task.
//
// Open the property sheet while we're still in the thread.
//
if (SUCCEEDED(hr) && pThis->_fAdvanced) { DEBUG_ASSERT(pThis->_pTask); DEBUG_ASSERT(*pThis->_tszJobObjectFullPath);
//
// Since we want to see the security page if the object is on NT
// on an NTFS partition, we'll have to call the version of
// DisplayJobProperties that takes a data object.
//
// To get a data object describing the task object, we need an
// itemid for the job, so create one.
//
CJobID jid;
jid.LoadDummy(pThis->_tszJobObjectFullPath); LPCITEMIDLIST pidl = (LPCITEMIDLIST) &jid;
LPDATAOBJECT pdo = NULL; TCHAR tszFolderPath[MAX_PATH + 1];
StringCchCopy(tszFolderPath, MAX_PATH + 1, pThis->_tszFolderPath); LPTSTR ptszLastSlash = _tcsrchr(tszFolderPath, TEXT('\\'));
if (ptszLastSlash && lstrlen(ptszLastSlash) == 1) { *ptszLastSlash = TEXT('\0'); }
hr = JFGetDataObject(tszFolderPath, // path to tasks dir
pThis->_pidlFolder, // itemid of tasks folder
1, // one itemid in array
&pidl, // namely, this one
FALSE, // not doing cut/paste
(VOID **) &pdo);
if (SUCCEEDED(hr)) { hr = DisplayJobProperties(pdo); CHECK_HRESULT(hr); } else { DEBUG_OUT_HRESULT(hr); } }
delete pThis; } __finally { OleUninitialize(); }
return (DWORD) hr; }
//+--------------------------------------------------------------------------
//
// Member: CTaskWizard::_DoWizard
//
// Synopsis: Create the wizard pages and invoke the wizard.
//
// Returns: HRESULT
//
// History: 5-20-1997 DavidMun Created
//
// Notes: If wizard is successfully created, doesn't return until
// user hits Cancel or Finish.
//
//---------------------------------------------------------------------------
HRESULT CTaskWizard::_DoWizard() { TRACE_METHOD(CTaskWizard, _DoWizard);
HRESULT hr = S_OK; UINT i = 0; HPROPSHEETPAGE ahpsp[NUM_TASK_WIZARD_PAGES];
SecureZeroMemory(ahpsp, sizeof(ahpsp));
do { //
// Create all the wizard pages
//
_apWizPages[TWP_WELCOME ] = new CWelcomePage (this, _tszFolderPath, &ahpsp[TWP_WELCOME ]); _apWizPages[TWP_SELECT_PROGRAM] = new CSelectProgramPage(this, _tszFolderPath, &ahpsp[TWP_SELECT_PROGRAM]); _apWizPages[TWP_SELECT_TRIGGER] = new CSelectTriggerPage(this, _tszFolderPath, &ahpsp[TWP_SELECT_TRIGGER]); _apWizPages[TWP_DAILY ] = new CDailyPage (this, _tszFolderPath, &ahpsp[TWP_DAILY ]); _apWizPages[TWP_WEEKLY ] = new CWeeklyPage (this, _tszFolderPath, &ahpsp[TWP_WEEKLY ]); _apWizPages[TWP_MONTHLY ] = new CMonthlyPage (this, _tszFolderPath, &ahpsp[TWP_MONTHLY ]); _apWizPages[TWP_ONCE ] = new COncePage (this, _tszFolderPath, &ahpsp[TWP_ONCE ]); _apWizPages[TWP_PASSWORD ] = new CPasswordPage (this, _tszFolderPath, &ahpsp[TWP_PASSWORD ]); _apWizPages[TWP_COMPLETION ] = new CCompletionPage (this, _tszFolderPath, &ahpsp[TWP_COMPLETION ]);
//
// Check that all objects and pages could be created
//
for (i = 0; i < NUM_TASK_WIZARD_PAGES; i++) { if (!_apWizPages[i] || !ahpsp[i]) { hr = E_OUTOFMEMORY; break; } }
//
// Manually destroy the pages if one could not be created, then exit
//
if (FAILED(hr)) { DEBUG_OUT((DEB_ERROR, "Creation failed, destroying pages\n"));
for (i = 0; i < NUM_TASK_WIZARD_PAGES; i++) { if (ahpsp[i]) { VERIFY(DestroyPropertySheetPage(ahpsp[i])); } else if (_apWizPages[i]) { delete _apWizPages[i]; } } break; }
//
// All pages created, display the wizard
//
PROPSHEETHEADER psh;
SecureZeroMemory(&psh, sizeof(psh));
#ifdef WIZARD97
psh.dwFlags = PSH_WIZARD | PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER; psh.pszbmWatermark = _fUse256ColorBmp ? MAKEINTRESOURCE(IDB_WATERMARK256) : MAKEINTRESOURCE(IDB_WATERMARK16); psh.pszbmHeader = _fUse256ColorBmp ? MAKEINTRESOURCE(IDB_BANNER256) : MAKEINTRESOURCE(IDB_BANNER16); #else
psh.dwFlags = PSH_WIZARD; #endif // WIZARD97
psh.dwSize = sizeof(psh); psh.hInstance = g_hInstance; psh.hwndParent = NULL; psh.pszCaption = NULL; // ignored for wizards; see CWelcome init
psh.phpage = ahpsp; psh.nStartPage = 0; psh.nPages = NUM_TASK_WIZARD_PAGES;
if (PropertySheet(&psh) == -1) { hr = HRESULT_FROM_WIN32(GetLastError()); DEBUG_OUT_HRESULT(hr); } } while (0);
return hr; }
//+--------------------------------------------------------------------------
//
// Function: FindWizardEnumWndProc
//
// Synopsis: EnumWindows callback used to search for a create new task
// wizard opened on the specified focus.
//
// Arguments: [hwnd] - top level window handle
// [lParam] - pointer to SFindWiz struct
//
// Returns: TRUE - not found, continue enumeration
// FALSE - found wizard, quit enumerating
//
// Modifies: SFindWiz struct pointed to by [lParam]
//
// History: 5-20-1997 DavidMun Created
//
//---------------------------------------------------------------------------
BOOL CALLBACK FindWizardEnumWndProc( HWND hwnd, LPARAM lParam) { SFindWiz *pfw = (SFindWiz *) lParam; ULONG pid;
GetWindowThreadProcessId(hwnd, &pid);
do { //
// If the window isn't in this process (explorer.exe) then ignore
// it.
//
if (pid != GetCurrentProcessId()) { break; }
//
// If it isn't the dialog class, it can't be a wizard.
//
if (!IsDialogClass(hwnd)) { break; }
//
// Found a dialog window that was created by this process. If it's
// a wizard, then it should return a valid window which is also of
// dialog class.
//
HWND hwndPage = PropSheet_GetCurrentPageHwnd(hwnd);
if (!IsWindow(hwndPage) || !IsDialogClass(hwndPage)) { break; }
//
// Could be a wizard page. Ask it if it's THE wizard for the
// focus. Note it's only possible to get away with sending a pointer
// in the message because we've guaranteed the window belongs to this
// process.
//
ULONG ulResult = (ULONG)SendMessage(hwndPage, g_msgFindWizard, 0, (LPARAM) pfw->tszFocus);
if (ulResult == g_msgFindWizard) { pfw->fFound = TRUE; } } while (0);
return !pfw->fFound; // continue enumerating if not found
}
//+--------------------------------------------------------------------------
//
// Member: CTaskWizard::_FindWizard
//
// Synopsis: Search through top level windows to find a create new task
// wizard which is focused on [ptszFolderPath].
//
// Arguments: [ptszFolderPath] - wizard focus
//
// Returns: S_OK - found
// S_FALSE - not found
//
// History: 5-20-1997 DavidMun Created
//
// Notes: BUGBUG change ptszFolderPath to server name
//
//---------------------------------------------------------------------------
HRESULT CTaskWizard::_FindWizard( LPCTSTR ptszFolderPath) { SFindWiz fw = { FALSE, ptszFolderPath };
if (!g_msgFindWizard) { g_msgFindWizard = RegisterWindowMessage(TEMPLATE_STR); }
EnumWindows(FindWizardEnumWndProc, (LPARAM) &fw);
return fw.fFound ? S_OK : S_FALSE; }
|