|
|
//____________________________________________________________________________
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1995 - 1996.
//
// File: jobidl.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: 1/24/1996 RaviR Created
//
//____________________________________________________________________________
#include "..\pch\headers.hxx"
#pragma hdrstop
#include "dbg.h"
#include "macros.h"
#include "..\inc\resource.h"
#include "resource.h"
#include "..\wizard\resource.h"
#include "..\inc\common.hxx"
#include "jobidl.hxx"
#include "sch_cls.hxx" // sched\inc
#include "job_cls.hxx" // sched\inc
#include "misc.hxx" // sched\inc
#include "util.hxx"
#include "..\schedui\schedui.hxx"
#if !defined(_CHICAGO_)
void SecurityErrorDialog( HWND hWndOwner, HRESULT hr); #endif // !defined(_CHICAGO_)
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
////////
//////// CJobID class implementation
////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//+--------------------------------------------------------------------------
//
// Member: CJobID::InitToTemplate
//
// Synopsis: Inititialize this to represent a template object in the
// folder.
//
// History: 05-15-1997 DavidMun Created
//
//---------------------------------------------------------------------------
void CJobID::InitToTemplate() { _id = ID_TEMPLATE;
//
// Name offset is at 1 so the first char can serve to make empty app
// name, creator, and path strings.
//
_oCreator = 0; _oPath = 0; _oName = 1;
LoadString(g_hInstance, IDS_TEMPLATE_NAME, &_cBuf[_oName], IDJOB_BUFFER_SIZE - 3); _cb = offsetof(CJobID, _cBuf) + (_oName + lstrlen(&_cBuf[_oName]) + 1) * sizeof(TCHAR); // ^^^ pidl size has to include offset into _cBuf
_NullTerminate(); }
//____________________________________________________________________________
//
// Member: CJobID::Load
//
// Arguments: [pszFolderPath] -- IN
// [pszJob] -- IN
//
// Returns: HRESULT.
//____________________________________________________________________________
HRESULT CJobID::Load( LPCTSTR pszFolderPath, LPTSTR pszJob) // job path relative to Jobs folder with .job extension
{ DEBUG_OUT((DEB_USER12, "[CJobID::Load] <%ws, %ws>\n", pszFolderPath ? (LPWSTR)pszFolderPath : L"NULL FolderPath", pszJob));
#if DBG==1
TCHAR * pExt = PathFindExtension(pszJob); Win4Assert(lstrcmpi(pExt, TSZ_DOTJOB) == 0); #endif
HRESULT hr = S_OK; CJob *pJob = NULL;
ZeroMemory(this, sizeof(CJobID));
do { //
// Set creation & last write times
//
TCHAR tcFile[MAX_PATH+1]; LPTSTR pFile = tcFile;
if (pszFolderPath != NULL) { lstrcpy(tcFile, pszFolderPath); lstrcat(tcFile, TEXT("\\")); lstrcat(tcFile, pszJob); } else { pFile = pszJob; }
//
// Skip hidden jobs.
//
if (GetFileAttributes(pFile) & FILE_ATTRIBUTE_HIDDEN) { return S_FALSE; }
HANDLE hFile = CreateFile(pFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile == INVALID_HANDLE_VALUE) { DEBUG_OUT_LASTERROR; hr = HRESULT_FROM_WIN32(GetLastError()); break; }
if (GetFileTime(hFile, &_ftCreation, NULL, &_ftLastWrite) == FALSE) { CloseHandle(hFile);
DEBUG_OUT_LASTERROR; hr = HRESULT_FROM_WIN32(GetLastError()); break; }
CloseHandle(hFile);
//
// Create & load the job
//
hr = ::JFCreateAndLoadCJob(pszFolderPath, pszJob, &pJob);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
_id = ID_JOB;
////////////////////////////////////////////////////////////
//
// Extract the properties
//
//
// Get last exit code
//
// The return value from this call is the task's last start error.
//
HRESULT hrLastStart = pJob->GetExitCode(&_dwExitCode);
//
// Get a code to tell what to display in the "Status" column.
// For the purposes of this column the job can be:
// a. missed
// b. failed to start
// c. running
// d. other
//
ULONG ulAllFlags;
pJob->GetAllFlags(&ulAllFlags);
if (ulAllFlags & JOB_I_FLAG_MISSED) { _status = ejsMissed; } else if (FAILED(hrLastStart)) { switch(hrLastStart) { case HRESULT_FROM_WIN32(ERROR_LOGON_FAILURE): _status = ejsBadAcct; break;
case HRESULT_FROM_WIN32(ERROR_ACCOUNT_RESTRICTION): _status = ejsResAcct; break;
default: _status = ejsWouldNotStart; }
} else { HRESULT hrStatus = 0;
hr = pJob->GetStatus(&hrStatus);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
switch (hrStatus) { case SCHED_S_TASK_RUNNING: _status = ejsRunning; break;
case SCHED_S_TASK_NOT_SCHEDULED: _status = ejsNotScheduled; break; } }
//
// Get last run time
//
hr = pJob->GetMostRecentRunTime(&_stLastRunTime);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
// ensure wDayOfWeek is 0, else memcmp fails.
_stLastRunTime.wDayOfWeek = 0;
//
// Get next run time
//
hr = pJob->GetNextRunTime(&_stNextRunTime);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
// ensure wDayOfWeek is 0, else memcmp fails.
_stNextRunTime.wDayOfWeek = 0;
//
// Get the job flags
//
hr = pJob->GetFlags(&_ulJobFlags);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
//
// Get the first job trigger if any
//
hr = pJob->GetTriggerCount(&_cTriggers);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
if (_cTriggers > 0) { ITaskTrigger * pIJobTrigger = NULL;
hr = pJob->GetTrigger(0, &pIJobTrigger);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
_sJobTrigger.cbTriggerSize = sizeof(TASK_TRIGGER);
hr = pIJobTrigger->GetTrigger(&_sJobTrigger);
pIJobTrigger->Release();
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr); } else { _sJobTrigger.cbTriggerSize = 0; }
///////////////////////////////////////////////////////////////////
//
// Fill up the buffer cBuf
//
USHORT cchCurr = 0;
//
// Get the command
//
LPWSTR pwszCommand = NULL;
hr = pJob->GetApplicationName(&pwszCommand);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
#ifndef UNICODE
hr = UnicodeToAnsi(_cBuf, pwszCommand, MAX_PATH); CoTaskMemFree(pwszCommand); BREAK_ON_FAIL(hr); #else
lstrcpy(_cBuf, pwszCommand); CoTaskMemFree(pwszCommand); #endif
DEBUG_OUT((DEB_USER12, "Command = %ws\n", _cBuf));
// update size
cchCurr += lstrlen(_cBuf) + 1;
//
// Get the account name
//
_oCreator = cchCurr;
LPWSTR pwszCreator = NULL;
hr = pJob->GetCreator(&pwszCreator);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
#if defined(UNICODE)
lstrcpy(&_cBuf[_oCreator], pwszCreator); CoTaskMemFree(pwszCreator); #else
hr = UnicodeToAnsi(&_cBuf[_oCreator], pwszCreator, MAX_PATH); CoTaskMemFree(pwszCreator); BREAK_ON_FAIL(hr); #endif
// update size
cchCurr += lstrlen(&_cBuf[_oCreator]) + 1;
//
// Copy the job path
//
_oPath = cchCurr;
if (pszFolderPath == NULL) { pszJob = PathFindFileName(pszJob); }
lstrcpy(&_cBuf[_oPath], pszJob);
TCHAR * ptcPath = &_cBuf[_oPath]; TCHAR * ptcName = PathFindFileName(ptcPath); TCHAR * ptcExtn = PathFindExtension(ptcName);
if (ptcExtn) { *ptcExtn = TEXT('\0'); }
_oName = _oPath + (USHORT)(ptcName - ptcPath) * sizeof(TCHAR);
// update buff size
cchCurr += lstrlen(ptcPath) + 1;
//
// Finaly set the size
//
_cb = offsetof(CJobID, _cBuf) + cchCurr * sizeof(TCHAR);
//
// Ensure that the DWORD at the end is zero, used by ILClone, etc.
//
_NullTerminate();
} while (0);
if (pJob != NULL) { pJob->Release(); }
return hr; }
//____________________________________________________________________________
//
// Member: CJobID::Rename
//
// Synopsis: Loads this object with data from jidIn, except for
// the name which is set to lpszName.
//
// Arguments: [jidIn] -- IN
// [lpszName] -- IN
//
// Returns: HRESULT.
//
// History: 1/25/1996 RaviR Created
//
//____________________________________________________________________________
HRESULT CJobID::Rename( CJobID & jidIn, LPCOLESTR lpszNameIn) { ZeroMemory(this, sizeof(CJobID)); CopyMemory(this, &jidIn, jidIn.GetSize());
LPTSTR lpszName = (LPTSTR)lpszNameIn;
#if !defined(UNICODE)
CHAR cBufTemp[MAX_PATH];
HRESULT hr = UnicodeToAnsi(cBufTemp, lpszNameIn, MAX_PATH); if (FAILED(hr)) { return hr; } lpszName = cBufTemp; #endif
lstrcpy(&_cBuf[_oName], lpszName);
_cb = offsetof(CJobID, _cBuf) + (_oName + lstrlen(lpszName) + 1) * sizeof(TCHAR);
_NullTerminate(); return S_OK; }
//____________________________________________________________________________
//
// Member: CJobID::Clone
//
// Returns: CJobID *
//____________________________________________________________________________
CJobID * CJobID::Clone(void) { CJobID * pjid = (CJobID *) SHAlloc(_cb + sizeof(_cb));
if (pjid) { CopyMemory(pjid, this, _cb); pjid->_NullTerminate(); }
return pjid; }
#if (DBG == 1)
//+--------------------------------------------------------------------------
//
// Member: CJobID::Validate
//
// Synopsis: Assert if this job idlist object is invalid
//
// History: 12-04-1997 DavidMun Created
//
// Notes: For debugging only.
//
//---------------------------------------------------------------------------
VOID CJobID::Validate() { //
// Expect _cb to have been set to nonzero value
//
Win4Assert(_cb); Win4Assert(_cb < sizeof(CJobID));
//
// Expect all jobids to have a name. Offset should be nonzero because
// name is not the first string.
//
Win4Assert(_oName < IDJOB_BUFFER_SIZE);
//
// Expect that name is null terminated before the end of the buffer.
//
Win4Assert(_oName + lstrlen(GetName()) < IDJOB_BUFFER_SIZE);
//
// Expect the jobid itself to be null terminated
//
UNALIGNED USHORT *pusNextCB = (UNALIGNED USHORT *)(((BYTE *)this) + _cb); Win4Assert(_cb + sizeof(USHORT) <= sizeof(CJobID)); Win4Assert(!*pusNextCB); }
#endif // (DBG == 1)
BOOL GetLocaleDateTimeString( SYSTEMTIME* pst, DWORD dwDateFlags, DWORD dwTimeFlags, TCHAR szBuff[], int cchBuffLen, LPSHELLDETAILS lpDetails); //____________________________________________________________________________
//
// Member: CJobID::GetNextRunTimeString
//
// Synopsis: S
//
// Arguments: [tcBuff] -- IN
// [cchBuff] -- IN
// [fForComparison] -- IN
//
// Returns: HRESULT.
//
// History: 4/25/1996 RaviR Created
//
//____________________________________________________________________________
LPTSTR CJobID::GetNextRunTimeString( TCHAR tcBuff[], UINT cchBuff, BOOL fForComparison, LPSHELLDETAILS lpDetails) { if (this->IsJobNotScheduled() == TRUE) { LoadString(g_hInstance, IDS_NEVER, tcBuff, cchBuff); } else if (this->IsJobFlagOn(TASK_FLAG_DISABLED) == TRUE) { LoadString(g_hInstance, IDS_DISABLED, tcBuff, cchBuff); } else if (this->IsTriggerFlagOn(TASK_TRIGGER_FLAG_DISABLED)) { LoadString(g_hInstance, IDS_TRIGGER_DISABLED, tcBuff, cchBuff); } else if (this->GetTriggerType() == TASK_EVENT_TRIGGER_AT_SYSTEMSTART) { LoadString(g_hInstance, IDS_ON_STARTUP, tcBuff, cchBuff); } else if (this->GetTriggerType() == TASK_EVENT_TRIGGER_AT_LOGON) { LoadString(g_hInstance, IDS_ON_LOGON, tcBuff, cchBuff); } else if (this->GetTriggerType() == TASK_EVENT_TRIGGER_ON_IDLE) { LoadString(g_hInstance, IDS_WHEN_IDLE, tcBuff, cchBuff); } else { SYSTEMTIME &st = this->GetNextRunTime();
if (st.wYear == 0 || st.wMonth == 0 || st.wDay == 0) { LoadString(g_hInstance, IDS_NEVER, tcBuff, cchBuff); } else { if (fForComparison == TRUE) { return NULL; }
GetLocaleDateTimeString(&st, DATE_SHORTDATE, 0, tcBuff, cchBuff, lpDetails); } }
return tcBuff; }
//____________________________________________________________________________
//
// Function: HDROPFromJobIDList
//
// Synopsis: Create an HDROP for the files in the apjid array.
// Used for CF_HDROP format.
//
// Arguments: [cidl] -- IN
// [apjidl] -- IN
//
// Returns: HDROP
//
// History: 1/31/1996 RaviR Created
//
//____________________________________________________________________________
HDROP HDROPFromJobIDList( LPCTSTR pszFolderPath, UINT cidl, PJOBID * apjidl) { HDROP hMem = 0; LPDROPFILESTRUCT lpDrop; DWORD dwSize = 0;
if (cidl == 0) { return NULL; }
TCHAR tcFolder[MAX_PATH]; lstrcpy(tcFolder, pszFolderPath); lstrcat(tcFolder, TEXT("\\"));
USHORT cbFolderPathLen = (USHORT)(lstrlen(tcFolder) * sizeof(TCHAR));
//
// Walk the list and find out how much space we need.
//
dwSize = sizeof(DROPFILESTRUCT) + sizeof(TCHAR); // size + terminal nul
USHORT * pusPathLen = new USHORT[cidl * 2];
if (pusPathLen == NULL) { CHECK_HRESULT(E_OUTOFMEMORY); return NULL; }
USHORT * pusExtLen = &pusPathLen[cidl];
for (UINT i=0; i < cidl; i++) { pusPathLen[i] = (USHORT)(lstrlen(apjidl[i]->GetPath()) * sizeof(TCHAR));
pusExtLen[i] = (USHORT)((lstrlen(apjidl[i]->GetExtension()) + 1) * sizeof(TCHAR));
dwSize += cbFolderPathLen + pusPathLen[i] + pusExtLen[i]; }
//
// If it's bigger than the struct can hold, then bail.
// TODO: Return an error?
//
if (dwSize > 0x0000ffff) { delete [] pusPathLen; return NULL; }
//
// Allocate the buffer and fill it in.
//
hMem = (HDROP)GlobalAlloc(GHND, dwSize);
if (hMem == NULL) { delete [] pusPathLen; CHECK_HRESULT(E_OUTOFMEMORY); return NULL; }
lpDrop = (LPDROPFILESTRUCT) GlobalLock(hMem);
lpDrop->pFiles = (DWORD)(sizeof(DROPFILESTRUCT)); lpDrop->pt.x = 0; lpDrop->pt.y = 0; lpDrop->fNC = FALSE; #ifdef UNICODE
lpDrop->fWide = TRUE; #else
lpDrop->fWide = FALSE; #endif
//
// Fill in the path names.
//
LPBYTE pbTemp = (LPBYTE) ((LPBYTE) lpDrop + lpDrop->pFiles);
for (i=0; i < cidl; i++) { CopyMemory(pbTemp, tcFolder, cbFolderPathLen); pbTemp += cbFolderPathLen;
CopyMemory(pbTemp, apjidl[i]->GetPath(), pusPathLen[i]); pbTemp += pusPathLen[i];
CopyMemory(pbTemp, apjidl[i]->GetExtension(), pusExtLen[i]); pbTemp += pusExtLen[i]; }
*((LPTSTR)pbTemp) = TEXT('\0'); // Extra Nul terminate
//
// Unlock the buffer and return it.
//
GlobalUnlock(hMem);
delete [] pusPathLen;
return hMem; }
//+--------------------------------------------------------------------------
//
// Function: CreateIDListArray
//
// Synopsis: Create shell idlist array in the format required by the
// CFSTR_SHELLIDLIST clipboard format.
//
// Arguments: [pidlFolder] - pidl of tasks folder
// [cidl] - number of elements in [apjidl]
// [apjidl] - array of pointers to idls, each idl
// specifies a .job object.
//
// Returns: Handle to created array, or NULL on error.
//
// History: 05-30-1997 DavidMun Created
//
// Notes: For this format, the first element in the array is an
// absolute idl to a container (the tasks folder), and the
// remainder (each a single .job object) are relative to the
// first.
//
//---------------------------------------------------------------------------
HGLOBAL CreateIDListArray( LPCITEMIDLIST pidlFolder, UINT cidl, PJOBID *apjidl) { TRACE_FUNCTION(CreateIDListArray);
Win4Assert(cidl); if (cidl == 0) { return NULL; }
HJOBIDA hJobIDA = NULL; DWORD offset = sizeof(CJobIDA) + sizeof(UINT) * cidl; DWORD dwSize = offset;
for (UINT i=0; i < cidl ; i++) { dwSize += apjidl[i]->GetSize() + 2; // +2 for null list terminator
}
dwSize += ILGetSize(pidlFolder);
hJobIDA = GlobalAlloc(GPTR, dwSize); // This MUST be GlobalAlloc!!!
if (hJobIDA == NULL) { CHECK_HRESULT(E_OUTOFMEMORY); return NULL; }
PJOBIDA pJobIDA = (PJOBIDA)hJobIDA; // no need to lock
pJobIDA->cidl = cidl; // count doesn't include idl at offset 0,
pJobIDA->aoffset[0] = offset; // which is container
CopyMemory(((LPBYTE)pJobIDA)+offset, pidlFolder, ILGetSize(pidlFolder)); offset += ILGetSize(pidlFolder);
for (i=0; i < cidl ; i++) { UINT cbSize = apjidl[i]->GetSize();
pJobIDA->aoffset[i+1] = offset;
CopyMemory(((LPBYTE)pJobIDA)+offset, apjidl[i], cbSize);
offset += cbSize + 2; // +2 to leave null after copied in idl
}
Win4Assert(offset == dwSize); return hJobIDA; }
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
////////
//////// CJobIDA related functions.
////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//____________________________________________________________________________
//
// Function: HJOBIDA_Create
//
// Synopsis: Create an HJOBIDA for the files in the apjid array.
// Used for CF_JOBIDLIST data format.
//
// Arguments: [cidl] -- IN
// [apjidl] -- IN
//
// Returns: HJOBIDA
//
// History: 1/31/1996 RaviR Created
//
//____________________________________________________________________________
HJOBIDA HJOBIDA_Create( UINT cidl, PJOBID * apjidl) { if (cidl == 0) { return NULL; }
HJOBIDA hJobIDA = NULL; DWORD offset = sizeof(CJobIDA) + sizeof(UINT) * (cidl - 1); DWORD dwSize = offset;
for (UINT i=0; i < cidl ; i++) { dwSize += apjidl[i]->GetSize() + 2; // +2 for null list terminator
}
hJobIDA = GlobalAlloc(GPTR, dwSize); // This MUST be GlobalAlloc with
// GPTR!
if (hJobIDA == NULL) { CHECK_HRESULT(E_OUTOFMEMORY); return NULL; }
PJOBIDA pJobIDA = (PJOBIDA)hJobIDA; // no need to lock
pJobIDA->cidl = cidl;
//
// Note that apjidl[i] reports its true size, which doesn't include the
// extra 0 ulong following it. That null terminator is required, and
// isn't copied into pJobIDA by the CopyMemory, which is using
// apjidl[i]'s reported size.
//
// Since the GPTR ensures zero-initialized memory, and the extra 2
// bytes per jobid has been accounted for in computing dwSize, we can
// get the terminator just by increasing offset by the terminator size
// on each iteration.
//
for (i=0; i < cidl ; i++) { UINT cbSize = apjidl[i]->GetSize();
pJobIDA->aoffset[i] = offset;
CopyMemory(((LPBYTE)pJobIDA)+offset, apjidl[i], cbSize);
offset += cbSize + 2; }
Win4Assert(offset == dwSize);
return hJobIDA; }
void HJOBIDA_Free( HJOBIDA hJobIDA) { GlobalFree(hJobIDA); // This MUST be GlobalFree
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
////////
//////// Functions to clone and free a LPCITEMIDLIST array.
////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//____________________________________________________________________________
//
// Function: ILA_Clone
//
// Synopsis: S
//
// Arguments: [cidl] -- IN
// [apidl] -- IN
//
// Returns: LPITEMIDLIST
//
// History: 1/9/1996 RaviR Created
//
//____________________________________________________________________________
LPITEMIDLIST* ILA_Clone( UINT cidl, LPCITEMIDLIST * apidl) { TRACE_FUNCTION(ILA_Clone);
LPITEMIDLIST* aNewPidl = new LPITEMIDLIST[cidl];
if (NULL == aNewPidl) { return NULL; }
for (UINT i = 0; i < cidl; i++) { aNewPidl[i] = ILClone(apidl[i]);
if (NULL == aNewPidl[i]) { // delete what we've allocated so far
for (UINT j = 0; j < i; j++) { ILFree(aNewPidl[i]); }
delete[] aNewPidl;
return NULL; } }
return aNewPidl; }
//____________________________________________________________________________
//
// Function: ILA_Free
//
// Synopsis: S
//
// Arguments: [cidl] -- IN
// [apidl] -- IN
//
// Returns: VOID
//
// History: 1/9/1996 RaviR Created
//
//____________________________________________________________________________
VOID ILA_Free( UINT cidl, LPITEMIDLIST * apidl) { TRACE_FUNCTION(ILA_Free);
for (UINT i = 0; i < cidl; i++) { ILFree(apidl[i]); }
delete [] apidl; }
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
////////
//////// Functions to access the CJob & CSchedule
////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//____________________________________________________________________________
//
// Function: JFGetJobScheduler
//
// Synopsis: S
//
// Arguments: [ppJobScheduler] -- IN
// [ppwszFolderPath] -- IN
//
// Returns: HRESULT
//
// History: 1/25/1996 RaviR Created
//
//____________________________________________________________________________
HRESULT JFGetJobScheduler( LPTSTR pszMachine, ITaskScheduler ** ppJobScheduler, LPCTSTR *ppszFolderPath) { HRESULT hr = S_OK; CSchedule * pCSchedule = NULL;
do { pCSchedule = new CSchedule;
if (pCSchedule == NULL) { hr = E_OUTOFMEMORY; CHECK_HRESULT(hr); break; }
hr = pCSchedule->Init();
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
if (pszMachine != NULL) { #ifdef UNICODE
hr = pCSchedule->SetTargetComputer(pszMachine); #else
WCHAR wBuff[MAX_PATH]; hr = AnsiToUnicode(wBuff, pszMachine, MAX_PATH); CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
hr = pCSchedule->SetTargetComputer(wBuff); #endif
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr); }
*ppszFolderPath = pCSchedule->GetFolderPath();
*ppJobScheduler = (ITaskScheduler *)pCSchedule;
} while (0);
if (FAILED(hr) && pCSchedule != NULL) { pCSchedule->Release(); }
return hr; }
//____________________________________________________________________________
//
// Member: CreateAndLoadCJob
//
// Arguments: [pszJob] -- IN
// [ppJob] -- OUT
//
// Returns: HRESULT.
//____________________________________________________________________________
HRESULT JFCreateAndLoadCJob( LPCTSTR pszFolderPath, LPTSTR pszJob, // job path relative to the folder
CJob ** ppJob) { TRACE_FUNCTION(CreateAndLoadCJob);
*ppJob = NULL; // init for failure
CJob *pJob = CJob::Create();
if (pJob == NULL) { CHECK_HRESULT(E_OUTOFMEMORY); return E_OUTOFMEMORY; }
TCHAR buff[MAX_PATH]; LPTSTR pszJobPathTemp = pszJob;
if (pszFolderPath != NULL) { lstrcpy(buff, pszFolderPath); lstrcat(buff, TEXT("\\")); lstrcat(buff, pszJob);
pszJobPathTemp = buff; }
HRESULT hr = S_OK;
#if defined(UNICODE)
LPWSTR pwszJobPath = pszJobPathTemp; #else
WCHAR wcBuff[MAX_PATH]; hr = AnsiToUnicode(wcBuff, pszJobPathTemp, MAX_PATH);
if (FAILED(hr)) { pJob->Release(); CHECK_HRESULT(hr); return hr; } LPWSTR pwszJobPath = wcBuff; #endif
DEBUG_OUT((DEB_USER1, "Load Job <%ws>\n", pwszJobPath));
hr = pJob->Load(pwszJobPath, STGM_READWRITE | STGM_SHARE_EXCLUSIVE);
if (FAILED(hr)) { pJob->Release(); CHECK_HRESULT(hr); return hr; }
//
// Success, return the object
//
*ppJob = pJob; return hr; }
//+--------------------------------------------------------------------------
//
// Function: JFCreateAndLoadTask
//
// Synopsis: Create an in-memory task object and initialize it from
// [pszJob], returning the ITask interface on the object.
//
// Arguments: [pszFolderPath] - path to tasks folder
// [pszJob] - filename of job
// [ppITask] - filled with ITask interface ptr
//
// Returns: HRESULT
//
// Modifies: *[ppITask]
//
// History: 10-07-1997 DavidMun Created
//
// Notes: Caller must Release returned interface.
//
//---------------------------------------------------------------------------
HRESULT JFCreateAndLoadTask( LPCTSTR pszFolderPath, LPTSTR pszJob, // job path relative to the folder
ITask ** ppITask) { TRACE_FUNCTION(CreateAndLoadTask); HRESULT hr; CJob *pJob;
hr = JFCreateAndLoadCJob(pszFolderPath, pszJob, &pJob);
if (SUCCEEDED(hr)) { hr = pJob->QueryInterface(IID_ITask, (void **)ppITask); pJob->Release(); }
return hr; }
//____________________________________________________________________________
//
// Function: JFSaveJob
//
// Synopsis: Save task settings to storage via the task's IPersistFile
// interface. Also, if applicable, prompt the user for security
// account information.
//
// Arguments: [hwndOwner] -- Owner window.
// [pIJob] -- Target task object.
// [fSecuritySupported] -- Flag indicating if
// security-specific code
// should be invoked.
// [fTaskAccountChange] -- TRUE, the task account
// information has
// changed.
// [fTaskApplicationChange] -- TRUE, the task
// application has
// changed.
// [fSuppressAccountInformationRequest] -- TRUE, do not prompt
// the user for account
// information.
//
// Returns: HRESULT
//
// History: 4/25/1996 RaviR Created
//
//____________________________________________________________________________
HRESULT JFSaveJob( HWND hwndOwner, ITask * pITask, BOOL fSecuritySupported, BOOL fTaskAccountChange, BOOL fTaskApplicationChange, BOOL fSuppressAccountInformationRequest) { #if defined(_CHICAGO_)
Win4Assert(!fSecuritySupported); #endif // defined(_CHICAGO_)
#if !defined(_CHICAGO_)
AccountInfo AcctInfo; #endif // !defined(_CHICAGO_)
HRESULT hr; IPersistFile * pipfTask; WCHAR * pwszAccountName = NULL; #if !defined(_CHICAGO_)
BOOL fChangesSaved = FALSE; #endif // !defined(_CHICAGO_)
hr = pITask->QueryInterface(IID_IPersistFile, (void **)&pipfTask);
if (FAILED(hr)) { return hr; }
#if !defined(_CHICAGO_)
if (fSecuritySupported) { InitializeAccountInfo(&AcctInfo);
//
// Application change but no corresponding account information change.
// Launch the set account information dialog in this case.
//
if (fTaskApplicationChange && !fTaskAccountChange) { //
// Attempt to retreive account information for the set account
// information dialog. Ignore failures, we would just like to
// have something to fill in the account name control.
//
if (SUCCEEDED(pITask->GetAccountInformation(&pwszAccountName))) { AcctInfo.pwszAccountName = pwszAccountName; }
goto SetAccountInformationDlg; } } #endif // !defined(_CHICAGO_)
//
// Go ahead and save the changes.
//
hr = pipfTask->Save(NULL, FALSE); #if !defined(_CHICAGO_)
fChangesSaved = TRUE; #endif // !defined(_CHICAGO_)
#if !defined(_CHICAGO_)
if (fSecuritySupported) { if (FAILED(hr)) { if (pipfTask->IsDirty() == S_FALSE) { //
// If Save failed, yet the job is no longer dirty, the
// error is due to a failure setting security information.
//
// Let the user know there was a problem. Remap the return
// code so we don't get further error dialogs.
//
CHECK_HRESULT(hr); SecurityErrorDialog(hwndOwner, hr); hr = S_OK; } #if DBG == 1
else { //
// Standard persist code failure. Calling page code will
// put up an error dialog.
//
CHECK_HRESULT(hr); } #endif // DBG == 1
goto CleanExit; }
if (!fTaskAccountChange) { //
// No account information changes. Verify that this job does
// indeed have account information associated with it.
//
hr = pITask->GetAccountInformation(&pwszAccountName);
if (hr == SCHED_E_ACCOUNT_INFORMATION_NOT_SET) { //
// No account information. Launch the set account information
// dialog.
//
hr = S_OK; goto SetAccountInformationDlg; } else if (SUCCEEDED(hr)) { //
// Done.
//
goto CleanExit; } else { //
// In error cases, silently fail. There's nothing we can do
// about it other than confuse the user. Remapping the return
// code so the calling page code doesn't put up an error
// dialog.
//
CHECK_HRESULT(hr); hr = S_OK; goto CleanExit; } } else if (fTaskApplicationChange && fTaskAccountChange) { //
// Fetch cached account information from the job object for
// the pending set account information dialog. Silently fail
// in an error case.
//
hr = pITask->GetAccountInformation(&pwszAccountName);
Win4Assert(hr != SCHED_E_ACCOUNT_INFORMATION_NOT_SET);
if (FAILED(hr) || hr == S_FALSE) { //
// The information is cached. This would fail for no
// reason other than insufficient memory.
//
// Though, did we goof?
//
CHECK_HRESULT(hr); hr = S_OK; goto CleanExit; }
AcctInfo.pwszAccountName = pwszAccountName; } else { //
// Done.
//
goto CleanExit; } } else { CHECK_HRESULT(hr); goto CleanExit; }
SetAccountInformationDlg:
//
// Should've arrived here only for security reasons.
//
Win4Assert(fSecuritySupported);
//
// Can only arrive at this point if the user must specify security
// account information.
//
// Launch the set account information dialog.
//
if (!fSuppressAccountInformationRequest) { LaunchSetAccountInformationDlg(hwndOwner, &AcctInfo);
//
// Check if the data is dirty. On dialog entry, the password is set
// to the global empty string. If the password ptr still equals this,
// then the user didn't change the password (e.g. the user canceled
// the dialog).
//
if (AcctInfo.pwszAccountName != NULL && AcctInfo.pwszPassword != tszEmpty) { //
// Reset the account information and persist the changes.
//
hr = pITask->SetAccountInformation(AcctInfo.pwszAccountName, AcctInfo.pwszPassword);
fChangesSaved = FALSE;
if (FAILED(hr)) { goto CleanExit; } } }
if (!fChangesSaved) { CWaitCursor WaitCursor; hr = pipfTask->Save(NULL, FALSE);
if (FAILED(hr) && pipfTask->IsDirty() == S_FALSE) { //
// Similar check as above. General save succeeded but the attempt
// to set security information failed. Let the user know there
// was a problem and remap the return code so we don't get
// further dialogs.
//
SecurityErrorDialog(hwndOwner, hr); hr = S_OK; } #if DBG == 1
else { CHECK_HRESULT(hr); } #endif // DBG == 1
} #endif // !defined(_CHICAGO_)
#if !defined(_CHICAGO_)
CleanExit: #endif // !defined(_CHICAGO_)
pipfTask->Release(); #if !defined(_CHICAGO_)
if (fSecuritySupported) { ResetAccountInfo(&AcctInfo); } #endif // !defined(_CHICAGO_)
return hr; }
#if !defined(_CHICAGO_)
//____________________________________________________________________________
//
// Function: SecurityErrorDialog
//
// Synopsis: Map the error to a hopefully friendly & informative dialog.
//
// Arguments: [hWndOwner] -- Parent window handle.
// [hr] -- Security error to map.
//
// Returns: None.
//
// Notes: None.
//
//____________________________________________________________________________
void SecurityErrorDialog( HWND hWndOwner, HRESULT hr) { int idsErrorMessage; UINT idsHelpHint;
idsErrorMessage = IERR_SECURITY_WRITE_ERROR;
if (hr == SCHED_E_ACCOUNT_NAME_NOT_FOUND) { idsHelpHint = IDS_HELP_HINT_INVALID_ACCT; } else if (hr == SCHED_E_ACCOUNT_DBASE_CORRUPT) { idsHelpHint = IDS_HELP_HINT_DBASE_CORRUPT; } else if (hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) { idsHelpHint = IDS_HELP_HINT_ACCESS_DENIED; } else if (hr == SCHED_E_SERVICE_NOT_RUNNING || HRESULT_FACILITY(hr) == FACILITY_RPC) { idsHelpHint = IDS_HELP_HINT_SEC_GENERAL; } else { //
// No help hint for unexpected errors.
//
idsHelpHint = 0; }
//
// Put up the error dialog.
//
SchedUIErrorDialog(hWndOwner, idsErrorMessage, hr, idsHelpHint); } #endif // !defined(_CHICAGO_)
//____________________________________________________________________________
//
// Function: JFGetAppNameForTask
//
// Synopsis: S
//
// Arguments: [path] -- IN
// [pszAppName] -- IN
// [cchAppName] -- IN
//
// Returns: HRESULT
//
// History: 4/25/1996 RaviR Created
//
//____________________________________________________________________________
HRESULT JFGetAppNameForTask( LPCTSTR pszTask, // Full path
LPTSTR pszAppName, UINT cchAppName) { TRACE_FUNCTION(JFGetAppNameForTask);
HRESULT hr = S_OK;
CJob *pJob = CJob::Create();
if (pJob == NULL) { CHECK_HRESULT(E_OUTOFMEMORY); return E_OUTOFMEMORY; }
hr = pJob->LoadP(pszTask, 0, FALSE, FALSE);
CHECK_HRESULT(hr);
if (SUCCEEDED(hr)) { LPWSTR pwszCommand = NULL;
hr = pJob->GetApplicationName(&pwszCommand);
CHECK_HRESULT(hr);
if (SUCCEEDED(hr)) { #ifdef UNICODE
lstrcpy(pszAppName, pwszCommand); DEBUG_OUT((DEB_USER1, "JFGetAppNameForTask -> %ws\n", pszAppName)); #else
hr = UnicodeToAnsi(pszAppName, pwszCommand, cchAppName); #endif
CoTaskMemFree(pwszCommand); } }
pJob->Release();
return hr; }
BOOL IsAScheduleObject( TCHAR szFile[]) { if( NULL == szFile ) { return FALSE; }
LPTSTR pszName = PathFindFileName(szFile); LPTSTR pszExt = PathFindExtension(pszName);
if (lstrcmpi(pszExt, TSZ_DOTJOB) != 0) // && (lstrcmpi(pszExt, g_szDotQue) != 0)
{ return FALSE; }
return TRUE; }
//____________________________________________________________________________
//
// Function: JFCopyJob
//
// Synopsis: S
//
// Arguments: [hwndOwner] -- IN
// [szFileFrom] -- IN
// [pszFolderPath] -- IN
// [fMove] -- IN
//
// Returns: HRESULT
//
// History: 2/2/1996 RaviR Created
//
//____________________________________________________________________________
HRESULT JFCopyJob( HWND hwndOwner, TCHAR szFileFrom[], LPCTSTR pszFolderPath, BOOL fMove) { HRESULT hr = S_OK; ITask * pJob = NULL;
LPTSTR pszName = PathFindFileName(szFileFrom);
hr = JFCreateAndLoadTask(NULL, szFileFrom, &pJob);
if (FAILED(hr)) { if (hr == HRESULT_FROM_WIN32(ERROR_INVALID_DATA)) { SchedUIErrorDialog(hwndOwner, IERR_INVALID_DATA, pszName); }
return hr; } else { pJob->Release(); }
TCHAR szFileTo[MAX_PATH+1]; lstrcpy(szFileTo, pszFolderPath);
SHFILEOPSTRUCT fo = {hwndOwner, (fMove ? FO_MOVE : FO_COPY), szFileFrom, szFileTo, FOF_ALLOWUNDO, FALSE, NULL, NULL};
// Make sure we have double trailing NULL!
*(szFileFrom + lstrlen(szFileFrom) + 1) = TEXT('\0');
if ((SHFileOperation(&fo) !=0) || fo.fAnyOperationsAborted == TRUE) { hr = E_FAIL; CHECK_HRESULT(hr); return hr; }
//SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_PATH, szFileFrom, szFileTo);
return hr; }
//____________________________________________________________________________
//
// Function: GetTriggerStringFromTrigger
//
// Synopsis: S
//
// Arguments: [pJobTrigger] -- IN
// [psTrigger] -- IN
// [cchTrigger] -- IN
//
// Returns: HRESULT
//____________________________________________________________________________
HRESULT GetTriggerStringFromTrigger( TASK_TRIGGER * pJobTrigger, LPTSTR psTrigger, UINT cchTrigger, LPSHELLDETAILS lpDetails) { HRESULT hr = S_OK; LPWSTR pwsz = NULL;
if (pJobTrigger->cbTriggerSize > 0) { hr = ::StringFromTrigger(pJobTrigger, &pwsz, lpDetails);
CHECK_HRESULT(hr);
if (SUCCEEDED(hr)) { #if defined(UNICODE)
lstrcpy(psTrigger, pwsz); #else
hr = UnicodeToAnsi(psTrigger, pwsz, cchTrigger); #endif
CoTaskMemFree(pwsz); } } else { LoadString(g_hInstance, IDS_JOB_NOT_SCHEDULED, psTrigger, cchTrigger); }
return hr; }
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
////////
//////// Misc functions.
////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
LPITEMIDLIST * SHIDLFromJobIDL( UINT cidl, PJOBID * apjidl) { LPITEMIDLIST * apidlOut = (LPITEMIDLIST *)SHAlloc( sizeof(LPITEMIDLIST) * cidl);
if (apidlOut) { for (UINT i=0; i < cidl; i++) { apidlOut[i] = ILCreateFromPath(apjidl[i]->GetPath());
if (apidlOut[i] == NULL) { break; } }
if (i < cidl) // => memory error
{ while (i--) { ILFree(apidlOut[i]); }
SHFree(apidlOut);
apidlOut = NULL; } }
#if DBG==1
if (apidlOut == NULL) { CHECK_HRESULT(E_OUTOFMEMORY); } #endif
return apidlOut; }
|