You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1752 lines
43 KiB
1752 lines
43 KiB
//____________________________________________________________________________
|
|
//
|
|
// 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"
|
|
|
|
void
|
|
SecurityErrorDialog(
|
|
HWND hWndOwner,
|
|
HRESULT hr);
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
////////
|
|
//////// 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;
|
|
|
|
SecureZeroMemory(this, sizeof(CJobID));
|
|
|
|
do
|
|
{
|
|
//
|
|
// Set creation & last write times
|
|
//
|
|
|
|
WCHAR tcFile[MAX_PATH+1];
|
|
LPTSTR pFile = tcFile;
|
|
|
|
if (pszFolderPath != NULL)
|
|
{
|
|
StringCchCopy(tcFile, MAX_PATH+1, pszFolderPath);
|
|
StringCchCat(tcFile, MAX_PATH+1, TEXT("\\"));
|
|
StringCchCat(tcFile, MAX_PATH+1, pszJob);
|
|
}
|
|
else
|
|
{
|
|
pFile = pszJob;
|
|
}
|
|
|
|
//
|
|
// Skip hidden jobs.
|
|
//
|
|
|
|
if (GetFileAttributes(pFile) & FILE_ATTRIBUTE_HIDDEN)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
HANDLE hFile = NULL;
|
|
HRESULT hr = OpenFileWithRetry(pFile, GENERIC_READ, FILE_SHARE_READ, &hFile);
|
|
if (FAILED(hr))
|
|
{
|
|
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);
|
|
|
|
StringCchCopy(_cBuf, IDJOB_BUFFER_SIZE, pwszCommand);
|
|
CoTaskMemFree(pwszCommand);
|
|
|
|
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);
|
|
|
|
StringCchCopy(&_cBuf[_oCreator], IDJOB_BUFFER_SIZE - _oCreator, pwszCreator);
|
|
CoTaskMemFree(pwszCreator);
|
|
|
|
|
|
// update size
|
|
cchCurr += lstrlen(&_cBuf[_oCreator]) + 1;
|
|
|
|
//
|
|
// Copy the job path
|
|
//
|
|
|
|
_oPath = cchCurr;
|
|
|
|
if (pszFolderPath == NULL)
|
|
{
|
|
pszJob = PathFindFileName(pszJob);
|
|
}
|
|
|
|
StringCchCopy(&_cBuf[_oPath], IDJOB_BUFFER_SIZE - _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)
|
|
{
|
|
SecureZeroMemory(this, sizeof(CJobID));
|
|
CopyMemory(this, &jidIn, jidIn.GetSize());
|
|
|
|
LPTSTR lpszName = (LPTSTR)lpszNameIn;
|
|
|
|
StringCchCopy(&_cBuf[_oName], IDJOB_BUFFER_SIZE - _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 +1];
|
|
StringCchCopy(tcFolder, MAX_PATH +1, pszFolderPath);
|
|
StringCchCat(tcFolder, MAX_PATH +1, 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;
|
|
lpDrop->fWide = TRUE;
|
|
|
|
//
|
|
// 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)
|
|
{
|
|
hr = pCSchedule->SetTargetComputer(pszMachine);
|
|
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 +1];
|
|
LPTSTR pszJobPathTemp = pszJob;
|
|
|
|
if (pszFolderPath != NULL)
|
|
{
|
|
StringCchCopy(buff, MAX_PATH +1, pszFolderPath);
|
|
StringCchCat(buff, MAX_PATH +1, TEXT("\\"));
|
|
StringCchCat(buff, MAX_PATH +1, pszJob);
|
|
|
|
pszJobPathTemp = buff;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
LPWSTR pwszJobPath = pszJobPathTemp;
|
|
|
|
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)
|
|
{
|
|
AccountInfo AcctInfo;
|
|
HRESULT hr;
|
|
IPersistFile * pipfTask;
|
|
WCHAR * pwszAccountName = NULL;
|
|
BOOL fChangesSaved = FALSE;
|
|
|
|
hr = pITask->QueryInterface(IID_IPersistFile, (void **)&pipfTask);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Go ahead and save the changes.
|
|
//
|
|
|
|
hr = pipfTask->Save(NULL, FALSE);
|
|
fChangesSaved = TRUE;
|
|
|
|
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
|
|
}
|
|
|
|
CleanExit:
|
|
pipfTask->Release();
|
|
if (fSecuritySupported)
|
|
{
|
|
ResetAccountInfo(&AcctInfo);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// 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);
|
|
}
|
|
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// 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))
|
|
{
|
|
StringCchCopy(pszAppName, cchAppName, pwszCommand);
|
|
DEBUG_OUT((DEB_USER1, "JFGetAppNameForTask -> %ws\n", pszAppName));
|
|
|
|
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];
|
|
StringCchCopy(szFileTo, MAX_PATH +1, 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 (pwsz)
|
|
{
|
|
StringCchCopy(psTrigger, cchTrigger, pwsz);
|
|
CoTaskMemFree(pwsz);
|
|
}
|
|
else
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
|