|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1994 - 1996.
//
// File: util.cxx
//
// Contents: Miscellaneous utility functions.
//
// History: 04-04-95 DavidMun Created
//
//----------------------------------------------------------------------------
#include <headers.hxx>
#pragma hdrstop
#include <msterr.h>
#include "jt.hxx"
//
// Local constants
//
const ULONG MONTH_INDEX_JAN = 0; const ULONG MONTH_INDEX_FEB = 1; const ULONG MONTH_INDEX_MAR = 2; const ULONG MONTH_INDEX_APR = 3; const ULONG MONTH_INDEX_MAY = 4; const ULONG MONTH_INDEX_JUN = 5; const ULONG MONTH_INDEX_JUL = 6; const ULONG MONTH_INDEX_AUG = 7; const ULONG MONTH_INDEX_SEP = 8; const ULONG MONTH_INDEX_OCT = 9; const ULONG MONTH_INDEX_NOV = 10; const ULONG MONTH_INDEX_DEC = 11;
const ULONG MONTHS_PER_YEAR = 12;
//+---------------------------------------------------------------------------
//
// Function: GetPriorityString
//
// Synopsis: Return a human-readable string representing [dwPriority].
//
// Arguments: [dwPriority] - process priority
//
// Returns: static string
//
// History: 01-03-96 DavidMun Created
//
//----------------------------------------------------------------------------
LPCSTR GetPriorityString(DWORD dwPriority) { switch (dwPriority) { case IDLE_PRIORITY_CLASS: return "IDLE";
case NORMAL_PRIORITY_CLASS: return "NORMAL";
case HIGH_PRIORITY_CLASS: return "HIGH";
case REALTIME_PRIORITY_CLASS: return "REALTIME"; } return "INVALID PRIORITY"; }
//+---------------------------------------------------------------------------
//
// Function: GetMonthsString
//
// Synopsis: Return a static string containing month names for each month
// bit turned on in [rgfMonths]
//
// Arguments: [rgfMonths] - TASK_JANUARY | TASK_FEBRUARY | ... |
// TASK_DECEMBER
//
// Returns: static string
//
// History: 03-07-96 DavidMun Created
//
//----------------------------------------------------------------------------
LPCWSTR GetMonthsString(WORD rgfMonths) { static WCHAR s_wszMonths[MONTHS_PER_YEAR * MONTH_ABBREV_LEN + 1];
s_wszMonths[0] = '\0';
if (rgfMonths & TASK_JANUARY) { wcscat(s_wszMonths, g_awszMonthAbbrev[MONTH_INDEX_JAN]); }
if (rgfMonths & TASK_FEBRUARY) { wcscat(s_wszMonths, g_awszMonthAbbrev[MONTH_INDEX_FEB]); }
if (rgfMonths & TASK_MARCH) { wcscat(s_wszMonths, g_awszMonthAbbrev[MONTH_INDEX_MAR]); }
if (rgfMonths & TASK_APRIL) { wcscat(s_wszMonths, g_awszMonthAbbrev[MONTH_INDEX_APR]); }
if (rgfMonths & TASK_MAY) { wcscat(s_wszMonths, g_awszMonthAbbrev[MONTH_INDEX_MAY]); }
if (rgfMonths & TASK_JUNE) { wcscat(s_wszMonths, g_awszMonthAbbrev[MONTH_INDEX_JUN]); }
if (rgfMonths & TASK_JULY) { wcscat(s_wszMonths, g_awszMonthAbbrev[MONTH_INDEX_JUL]); }
if (rgfMonths & TASK_AUGUST) { wcscat(s_wszMonths, g_awszMonthAbbrev[MONTH_INDEX_AUG]); }
if (rgfMonths & TASK_SEPTEMBER) { wcscat(s_wszMonths, g_awszMonthAbbrev[MONTH_INDEX_SEP]); }
if (rgfMonths & TASK_OCTOBER) { wcscat(s_wszMonths, g_awszMonthAbbrev[MONTH_INDEX_OCT]); }
if (rgfMonths & TASK_NOVEMBER) { wcscat(s_wszMonths, g_awszMonthAbbrev[MONTH_INDEX_NOV]); }
if (rgfMonths & TASK_DECEMBER) { wcscat(s_wszMonths, g_awszMonthAbbrev[MONTH_INDEX_DEC]); }
if (s_wszMonths[0] == '\0') { wcscpy(s_wszMonths, L"None"); }
return s_wszMonths; }
//+---------------------------------------------------------------------------
//
// Function: DumpJobFlags
//
// Synopsis: Dump description of [flJobFlags] to log.
//
// Arguments: [flJobFlags] - TASK_*
//
// History: 01-03-96 DavidMun Created
//
//----------------------------------------------------------------------------
VOID DumpJobFlags(DWORD flJobFlags) { #ifndef RES_KIT
g_Log.Write( LOG_TEXT, " Interactive = %u", (flJobFlags & TASK_FLAG_INTERACTIVE) != 0); #endif
g_Log.Write( LOG_TEXT, " DeleteWhenDone = %u", (flJobFlags & TASK_FLAG_DELETE_WHEN_DONE) != 0);
g_Log.Write( LOG_TEXT, " Suspend = %u", (flJobFlags & TASK_FLAG_DISABLED) != 0);
g_Log.Write( LOG_TEXT, " StartOnlyIfIdle = %u", (flJobFlags & TASK_FLAG_START_ONLY_IF_IDLE) != 0);
g_Log.Write( LOG_TEXT, " KillOnIdleEnd = %u", (flJobFlags & TASK_FLAG_KILL_ON_IDLE_END) != 0);
g_Log.Write( LOG_TEXT, " RestartOnIdleResume = %u", (flJobFlags & TASK_FLAG_RESTART_ON_IDLE_RESUME) != 0);
g_Log.Write( LOG_TEXT, " DontStartIfOnBatteries = %u", (flJobFlags & TASK_FLAG_DONT_START_IF_ON_BATTERIES) != 0);
g_Log.Write( LOG_TEXT, " KillIfGoingOnBatteries = %u", (flJobFlags & TASK_FLAG_KILL_IF_GOING_ON_BATTERIES) != 0);
g_Log.Write( LOG_TEXT, " RunOnlyIfLoggedOn = %u", (flJobFlags & TASK_FLAG_RUN_ONLY_IF_LOGGED_ON) != 0);
g_Log.Write( LOG_TEXT, " SystemRequired = %u", (flJobFlags & TASK_FLAG_SYSTEM_REQUIRED) != 0);
g_Log.Write( LOG_TEXT, " Hidden = %u", (flJobFlags & TASK_FLAG_HIDDEN) != 0);
flJobFlags = flJobFlags & ~(TASK_FLAG_INTERACTIVE | TASK_FLAG_DELETE_WHEN_DONE | TASK_FLAG_DISABLED | TASK_FLAG_START_ONLY_IF_IDLE | TASK_FLAG_KILL_ON_IDLE_END | TASK_FLAG_RESTART_ON_IDLE_RESUME | TASK_FLAG_DONT_START_IF_ON_BATTERIES | TASK_FLAG_KILL_IF_GOING_ON_BATTERIES | TASK_FLAG_RUN_ONLY_IF_LOGGED_ON | TASK_FLAG_SYSTEM_REQUIRED | TASK_FLAG_HIDDEN);
if (flJobFlags) { g_Log.Write(LOG_WARN, " Unrecognized bits = %x", flJobFlags); } }
//+---------------------------------------------------------------------------
//
// Function: DumpTriggers
//
// Synopsis: Print all triggers to the log.
//
// Arguments: [fJob] - TRUE=>print g_pJob triggers, FALSE=> use g_pJobQueue
//
// Returns: S_OK - all triggers printed
// E_* - error printing a trigger
//
// History: 01-10-96 DavidMun Created
//
//----------------------------------------------------------------------------
HRESULT DumpTriggers(BOOL fJob) { HRESULT hr = S_OK; USHORT i; USHORT cTriggers;
do { if (fJob) { hr = g_pJob->GetTriggerCount(&cTriggers); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetTriggerCount"); } else { #ifdef NOT_YET
hr = g_pJobQueue->GetTriggerCount(&cTriggers); LOG_AND_BREAK_ON_FAIL(hr, "ITaskQueue::GetTriggerCount"); #endif // NOT_YET
hr = E_NOTIMPL; }
g_Log.Write(LOG_TEXT, "");
if (!cTriggers) { g_Log.Write(LOG_TEXT, " No triggers"); break; }
g_Log.Write( LOG_TEXT, " %u Trigger%c", cTriggers, cTriggers == 1 ? ' ' : 's');
for (i = 0; i < cTriggers; i++) { hr = DumpTrigger(fJob, i); }
} while (0); return hr; }
//+---------------------------------------------------------------------------
//
// Function: DumpJob
//
// Synopsis: Write all job properties to the log.
//
// Arguments: [pJob] - job to dump
//
// Returns: S_OK - printed
// E_* - couldn't read all job properties
//
// History: 03-11-96 DavidMun Created
//
//----------------------------------------------------------------------------
HRESULT DumpJob(ITask *pJob) { HRESULT hr = S_OK; CJobProp JobProperties;
do { g_Log.Write(LOG_TRACE, "Printing all job properties");
//
// Print the properties of the job itself first
//
hr = JobProperties.InitFromActual(pJob); BREAK_ON_FAILURE(hr);
JobProperties.Dump(); } while (0); return hr; }
//+---------------------------------------------------------------------------
//
// Function: DumpJobTriggers
//
// Synopsis: Write properties of all triggers on job to the log.
//
// Arguments: [pJob] - job for which to write trigger properties to log
//
// Returns: S_OK - information printed
// E_* - couldn't read all trigger properties
//
// History: 03-11-96 DavidMun Created
//
//----------------------------------------------------------------------------
HRESULT DumpJobTriggers(ITask *pJob) { HRESULT hr = S_OK; USHORT i; USHORT cTriggers;
do { hr = pJob->GetTriggerCount(&cTriggers); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetTriggerCount");
g_Log.Write(LOG_TEXT, "");
if (!cTriggers) { g_Log.Write(LOG_TEXT, " No triggers"); break; }
g_Log.Write( LOG_TEXT, " %u Trigger%c", cTriggers, cTriggers == 1 ? ' ' : 's');
for (i = 0; i < cTriggers; i++) { SpIJobTrigger spTrigger; CTrigProp TriggerProperties;
hr = pJob->GetTrigger(i, &spTrigger); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetTrigger");
hr = TriggerProperties.InitFromActual(spTrigger); BREAK_ON_FAILURE(hr);
g_Log.Write(LOG_TEXT, ""); g_Log.Write(LOG_TEXT, " Trigger %u:", i); TriggerProperties.Dump(); } } while (0); return hr; }
//+---------------------------------------------------------------------------
//
// Function: DumpTrigger
//
// Synopsis: Print a single trigger to the log
//
// Arguments: [fJob] - TRUE=>print g_pJob triggers,
// FALSE=> use g_pJobQueue
// [usTrigger] - 0-based trigger index
//
// Returns: S_OK - trigger printed
// E_* - error printing a trigger
//
// History: 01-10-96 DavidMun Created
//
//----------------------------------------------------------------------------
HRESULT DumpTrigger(BOOL fJob, USHORT usTrigger) { HRESULT hr = S_OK; SpIJobTrigger spTrigger; CTrigProp TriggerProperties;
do { if (fJob) { hr = g_pJob->GetTrigger(usTrigger, &spTrigger); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetTrigger"); } else { #ifdef NOT_YET
hr = g_pJobQueue->GetTrigger(usTrigger, &spTrigger); LOG_AND_BREAK_ON_FAIL(hr, "ITaskQueue::GetTrigger"); #endif // NOT_YET
hr = E_NOTIMPL; }
hr = TriggerProperties.InitFromActual(spTrigger); BREAK_ON_FAILURE(hr);
g_Log.Write(LOG_TEXT, ""); g_Log.Write(LOG_TEXT, " Trigger %u:", usTrigger); TriggerProperties.Dump(); } while (0); return hr; }
//+---------------------------------------------------------------------------
//
// Function: GetInterfaceString
//
// Synopsis: Return string in the form IID_* or "unrecognized interface"
//
// Arguments: [iidToBind] - interface
//
// History: 04-25-95 DavidMun Created
// 09-11-95 DavidMun New interfaces
//
//----------------------------------------------------------------------------
LPCSTR GetInterfaceString(REFIID iid) { CHAR *szInterface;
if (&iid == &IID_IUnknown) { szInterface = "IID_IUnknown"; } else if (&iid == &IID_ITask) { szInterface = "IID_ITask"; } else if (&iid == &IID_ITaskTrigger) { szInterface = "IID_ITaskTrigger"; } else { szInterface = "unrecognized interface"; }
return szInterface; }
//+---------------------------------------------------------------------------
//
// Function: GetTriggerTypeString
//
// Synopsis: Return a static human-readable string describing
// [TriggerType].
//
// Arguments: [TriggerType] - TASK_TRIGGER_TYPE
//
// Returns: static string
//
// History: 01-04-96 DavidMun Created
// 06-13-96 DavidMun Logon trigger
//
//----------------------------------------------------------------------------
LPCSTR GetTriggerTypeString(TASK_TRIGGER_TYPE TriggerType) { switch (TriggerType) { case TASK_TIME_TRIGGER_ONCE: return "Once";
case TASK_TIME_TRIGGER_DAILY: return "Daily";
case TASK_TIME_TRIGGER_WEEKLY: return "Weekly";
case TASK_TIME_TRIGGER_MONTHLYDATE: return "MonthlyDate";
case TASK_TIME_TRIGGER_MONTHLYDOW: return "MonthlyDOW";
case TASK_EVENT_TRIGGER_ON_IDLE: return "OnIdle";
case TASK_EVENT_TRIGGER_AT_SYSTEMSTART: return "AtStartup";
case TASK_EVENT_TRIGGER_AT_LOGON: return "AtLogon"; } return "INVALID TRIGGER TYPE"; }
//+---------------------------------------------------------------------------
//
// Function: GetDaysString
//
// Synopsis: Returns static string representing day bits in
// [rgfDays].
//
// Arguments: [rgfDays] - each of the 32 bits corresponds to a day of the
// month.
//
// Returns: static string
//
// History: 03-07-96 DavidMun Created
//
// Notes: This routine supports "day 32" because if the job scheduler
// erroneously turns on that bit we want to make it visible.
//
//----------------------------------------------------------------------------
LPCSTR GetDaysString(DWORD rgfDays) { static CHAR s_szDaysList[] = "1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,32"; ULONG i; ULONG j; ULONG ulRunStart = 0; BOOL fInRun = FALSE;
//
// Note s_szDaysList is initialized to worst case to get adequately long
// string. The most significant bit may be set and we want to display
// that, so it includes space for 32.
//
s_szDaysList[0] = '\0';
for (i = 0; i <= 32; i++, rgfDays >>= 1) { if (rgfDays & 1) { //
// Day 'i' should be included in the string. If we're in a run of
// days that are on, simply continue. When the run ends we'll add
// it to the string.
//
// If we're not in a run of days, consider this day the start of
// a new run (which may turn out to be only one day long).
//
if (!fInRun) { fInRun = TRUE; ulRunStart = i; } } else if (fInRun) { //
// Bit i is a zero, so obviously we're not in a run of ones
// anymore. Turn off that flag.
//
fInRun = FALSE;
//
// The bits from ulRunStart to i-1 were all on. Find out if the
// run was just one or two bits long, if that's the case then
// we don't want to use the m-n list form, the day number(s) should
// simply be appended to the string.
//
// Note that at this point i must be >= 1.
//
if (i == 1) { // ulRunStart == 0. bit 0 was on, which corresponds to day 1.
strcpy(s_szDaysList, "1"); } else if (i == 2) { //
// ulRunStart == 0 or 1, so the run is 1 or 2 bits long. So
// we don't want to use a dash.
//
if (ulRunStart == 0) { strcpy(s_szDaysList, "1,2"); } else { strcpy(s_szDaysList, "2"); } } else if (ulRunStart <= i - 3) // i >= 3 at this point
{ // There's a run of > 2 bits, which means we want a dash
if (s_szDaysList[0]) { strcat(s_szDaysList, ","); }
//
// Remember we're converting from a bit position, which is 0
// based, to a day number, which is 1 based.
//
CHAR *pszNext;
pszNext = s_szDaysList + strlen(s_szDaysList); pszNext += wsprintfA(pszNext, "%u", ulRunStart + 1); *pszNext++ = '-'; wsprintfA(pszNext, "%u", i); } else { // There's a run of 1 or 2 bits
CHAR *pszNext = s_szDaysList + strlen(s_szDaysList);
for (j = ulRunStart; j < i; j++) { if (s_szDaysList[0]) { *pszNext++ = ','; }
pszNext += wsprintfA(pszNext, "%u", j+1); } } } } return s_szDaysList; }
//+---------------------------------------------------------------------------
//
// Function: GetDaysOfWeekString
//
// Synopsis: Returns static string representing day bits in
// [flDaysOfTheWeek].
//
// Arguments: [flDaysOfTheWeek] - TASK_*DAY bits
//
// Returns: static string
//
// History: 01-04-96 DavidMun Created
//
//----------------------------------------------------------------------------
LPCSTR GetDaysOfWeekString(WORD flDaysOfTheWeek) { static CHAR s_szDOW[] = "UMTWRFA"; // init to get max size
sprintf(s_szDOW, ".......");
if (flDaysOfTheWeek & TASK_SUNDAY) { s_szDOW[0] = 'U'; }
if (flDaysOfTheWeek & TASK_MONDAY) { s_szDOW[1] = 'M'; }
if (flDaysOfTheWeek & TASK_TUESDAY) { s_szDOW[2] = 'T'; }
if (flDaysOfTheWeek & TASK_WEDNESDAY) { s_szDOW[3] = 'W'; }
if (flDaysOfTheWeek & TASK_THURSDAY) { s_szDOW[4] = 'R'; }
if (flDaysOfTheWeek & TASK_FRIDAY) { s_szDOW[5] = 'F'; }
if (flDaysOfTheWeek & TASK_SATURDAY) { s_szDOW[6] = 'A'; } return s_szDOW; }
//+---------------------------------------------------------------------------
//
// Function: GetStatusString
//
// Synopsis: Return a string describing job status.
//
// Arguments: [hrJobStatus] - SCHED_* hresult
//
// Returns: static string
//
// History: 01-08-96 DavidMun Created
//
//----------------------------------------------------------------------------
LPCSTR GetStatusString(HRESULT hrJobStatus) { static CHAR s_szStatus[11]; // big enough for 0x00000000
switch (hrJobStatus) { case S_OK: return "S_OK";
case SCHED_S_TASK_READY: return "SCHED_S_TASK_READY";
case SCHED_S_TASK_RUNNING: return "SCHED_S_TASK_RUNNING";
case SCHED_S_TASK_DISABLED: return "SCHED_S_TASK_DISABLED";
case SCHED_S_TASK_TERMINATED: return "SCHED_S_TASK_TERMINATED";
case SCHED_S_TASK_HAS_NOT_RUN: return "SCHED_S_TASK_HAS_NOT_RUN";
case SCHED_S_TASK_NO_VALID_TRIGGERS: return "SCHED_S_TASK_NO_VALID_TRIGGERS";
case SCHED_S_TASK_NO_MORE_RUNS: return "SCHED_S_TASK_NO_MORE_RUNS";
case SCHED_S_TASK_NOT_SCHEDULED: return "SCHED_S_TASK_NOT_SCHEDULED";
case SCHED_E_TASK_NOT_RUNNING: return "SCHED_E_TASK_NOT_RUNNING";
case SCHED_E_SERVICE_NOT_INSTALLED: return "SCHED_E_SERVICE_NOT_INSTALLED";
case SCHED_E_ACCOUNT_INFORMATION_NOT_SET: return "SCHED_E_ACCOUNT_INFORMATION_NOT_SET";
#ifdef DELETED
case SCHED_E_NOT_AN_AT_JOB: return "SCHED_E_NOT_AN_AT_JOB"; #endif // DELETED
default: sprintf(s_szStatus, "%#x", hrJobStatus); return s_szStatus; } }
//+---------------------------------------------------------------------------
//
// Function: Bind
//
// Synopsis: Bind to [wszFilename] for [iidToBind].
//
// Arguments: [wszFilename] - file to bind to
// [iidToBind] - interface to request
// [ppitf] - resulting interface
//
// Returns: S_OK - *[ppitf] valid
// E_* - error logged
//
// Modifies: *[ppitf]
//
// History: 04-20-95 DavidMun Created
// 04-25-95 DavidMun Add performance output
//
//----------------------------------------------------------------------------
HRESULT Bind(WCHAR *wszFilename, REFIID iidToBind, VOID **ppitf) { HRESULT hr = S_OK; SpIMoniker spmk; ULONG ulTicks;
do { g_Log.Write( LOG_DEBUG, "Binding to %S for %s", wszFilename, GetInterfaceString(iidToBind));
hr = GetMoniker(wszFilename, &spmk); BREAK_ON_FAILURE(hr);
ulTicks = GetTickCount(); hr = BindMoniker(spmk, 0, iidToBind, ppitf); ulTicks = GetTickCount() - ulTicks;
g_Log.Write( LOG_PERF, "Bind to %S for %s %u ms", wszFilename, GetInterfaceString(iidToBind), ulTicks);
if (FAILED(hr)) { g_Log.Write( LOG_FAIL, "BindMoniker to \"%S\" hr=%#010x", wszFilename, hr); } } while (0); return hr; }
//+---------------------------------------------------------------------------
//
// Function: GetMoniker
//
// Synopsis: Return a filemoniker to [wszFilename].
//
// Arguments: [wszFilename] - file to get moniker for
// [ppmk] - resulting moniker
//
// Returns: S_OK - *[ppmk] valid
// E_* - error logged
//
// Modifies: *[ppmk]
//
// History: 04-20-95 DavidMun Created
//
//----------------------------------------------------------------------------
HRESULT GetMoniker(WCHAR *wszFilename, IMoniker **ppmk) { HRESULT hr = S_OK;
do { g_Log.Write(LOG_DEBUG, "Creating file moniker to %S", wszFilename); hr = CreateFileMoniker(wszFilename, ppmk);
if (FAILED(hr)) { g_Log.Write( LOG_FAIL, "CreateFileMoniker(\"%S\") hr=%#010x", wszFilename, hr); break; } } while (0); return hr; }
//+---------------------------------------------------------------------------
//
// Function: DupString
//
// Synopsis: Fill *[ppwszDest] with a buffer containing a copy of
// [wszSource].
//
// Arguments: [wszSource] - string to copy
// [ppwszDest] - filled with buffer containing copy
//
// Returns: S_OK
// E_OUTOFMEMORY;
//
// Modifies: *[ppwszDest]
//
// History: 04-20-95 DavidMun Created
//
// Notes: Caller must use delete to free *[ppwszDest].
//
//----------------------------------------------------------------------------
HRESULT DupString(const WCHAR *wszSource, WCHAR **ppwszDest) { HRESULT hr = S_OK;
*ppwszDest = (LPWSTR)CoTaskMemAlloc(sizeof(WCHAR) * (1 + wcslen(wszSource)));
if (!*ppwszDest) { hr = E_OUTOFMEMORY; g_Log.Write(LOG_ERROR, "DupString: out of memory"); } else { wcscpy(*ppwszDest, wszSource); } return hr; }
//+---------------------------------------------------------------------------
//
// Function: HasFilename
//
// Synopsis: Return S_OK if object has filename, S_FALSE if not.
//
// Arguments: [pPersistFile] - IPFile itf on object
//
// Returns: S_OK - object has filename
// S_FALSE - object does not have filename
// E_* - error logged
//
// History: 01-10-96 DavidMun Created
//
//----------------------------------------------------------------------------
HRESULT HasFilename(IPersistFile *pPersistFile) { HRESULT hr = S_OK; LPOLESTR pstrFile;
do { hr = pPersistFile->GetCurFile(&pstrFile); LOG_AND_BREAK_ON_FAIL(hr, "IPersistFile::GetCurFile");
CoTaskMemFree(pstrFile); } while (0); return hr; }
//+---------------------------------------------------------------------------
//
// Function: SaveIfDirty
//
// Synopsis: Save given job object if it's dirty.
//
// Arguments: [pJob] - job to save
//
// Returns: S_OK - not dirty or successfully saved
// E_* - error logged
//
// History: 01-10-96 DavidMun Created
//
//----------------------------------------------------------------------------
HRESULT SaveIfDirty(ITask *pJob) { HRESULT hr = S_OK; SpIPersistFile spPersistFile;
do { hr = pJob->QueryInterface(IID_IPersistFile, (void **)&spPersistFile); LOG_AND_BREAK_ON_FAIL(hr, "ITask::QI(IPersistFile)");
hr = _SaveIfDirty(spPersistFile); } while (0); return hr; }
//+---------------------------------------------------------------------------
//
// Function: SaveIfDirty
//
// Synopsis: Save queue object if it's dirty. See job object version.
//
// History: 01-10-96 DavidMun Created
//
//----------------------------------------------------------------------------
HRESULT SaveIfDirty(IUnknown *pJobQueue) { HRESULT hr = S_OK; SpIPersistFile spPersistFile;
do { hr = pJobQueue->QueryInterface( IID_IPersistFile, (void **)&spPersistFile); LOG_AND_BREAK_ON_FAIL(hr, "ITaskQueue::QI(IPersistFile)");
hr = _SaveIfDirty(spPersistFile); } while (0); return hr; }
//+---------------------------------------------------------------------------
//
// Function: _SaveIfDirty
//
// Synopsis: Save persisted object if it reports it's dirty.
//
// Arguments: [pPersistFile] - IPFile on job or queue
//
// Returns: S_OK - saved or not dirty
// E_* - error logged
//
// History: 01-10-96 DavidMun Created
//
//----------------------------------------------------------------------------
HRESULT _SaveIfDirty(IPersistFile *pPersistFile) { HRESULT hr = S_OK;
do { hr = HasFilename(pPersistFile); BREAK_ON_FAILURE(hr);
//
// If the object doesn't have a filename then it can't be persisted.
//
if (hr == S_FALSE) { break; }
//
// If the object isn't dirty, there's nothing to do
//
hr = pPersistFile->IsDirty(); LOG_AND_BREAK_ON_FAIL(hr, "IPersistFile::IsDirty");
if (hr == S_FALSE) { break; }
//
// Save the object.
//
hr = pPersistFile->Save(NULL, TRUE); LOG_AND_BREAK_ON_FAIL(hr, "IPersistFile::Save"); } while (0); return hr; }
//+---------------------------------------------------------------------------
//
// Function: Activate
//
// Synopsis: Perform the Activate command
//
// Arguments: [wszFileName] - name of job or queue to activate
// [ppJob] - filled if file is job
// [ppQueue] - filled if file is queue
// [pfJob] - set TRUE if [wszFileName] is a job, FALSE
// otherwise.
//
// Returns: S_OK - *[pfJob] and either *[ppJob] or *[ppQueue] valid
// E_* - error logged
//
// Modifies: *[pfJob], and either *[ppJob] or *[ppQueue]
//
// History: 01-30-96 DavidMun Created
//
//----------------------------------------------------------------------------
HRESULT Activate( WCHAR *wszFileName, ITask **ppJob, IUnknown **ppQueue, BOOL *pfJob) { HRESULT hr = S_OK; SpIJob spJob; SpIUnknown spQueue;
do { *pfJob = TRUE;
//
// BUGBUG remove this ifdef when ITaskScheduler::IsTask() and
// ITaskScheduler::IsQueue() are implemented.
//
#ifdef IS_JOB_IMPLEMENTED
hr = g_pJobScheduler->IsJob(wszFileName); LOG_AND_BREAK_ON_FAIL(hr, "ITaskScheduler::IsTask");
if (hr == S_FALSE) { hr = g_pJobScheduler->IsQueue(wszFileName);
if (hr == S_OK) { *pfJob = FALSE; } else { g_Log.Write( LOG_FAIL, "File '%S' is neither a job nor a queue, IsJob hr=S_FALSE, IsQueue hr=%#010x", wszFilename, hr); hr = E_FAIL; break; } } else if (hr != S_OK) { g_pLog->Write( LOG_FAIL, "Unexpected hr from IsJob: %#010x", hr); hr = E_FAIL; break; } #endif // IS_JOB_IMPLEMENTED
//
// Activate the job or queue and ask for the appropriate interface.
//
g_Log.Write( LOG_TRACE, "Activating %s '%S'", *pfJob ? "job" : "queue", wszFileName);
if (*pfJob) { hr = g_pJobScheduler->Activate( wszFileName, IID_ITask, (IUnknown**)(ITask**)&spJob); } else { hr = g_pJobScheduler->Activate( wszFileName, IID_IUnknown, (IUnknown**)&spQueue); }
//
// Bail if the activate failed
//
if (FAILED(hr)) { g_Log.Write( LOG_FAIL, "ITaskScheduler::Activate(%S, IID_ITask%s) hr=%#010x", wszFileName, *pfJob ? "" : "Queue", hr); break; }
//
// Replace the passed in job or queue object with the new one.
//
if (*pfJob) { if (*ppJob) { hr = SaveIfDirty(*ppJob); (*ppJob)->Release(); } spJob.Transfer(ppJob); } else { if (*ppQueue) { hr = SaveIfDirty(*ppQueue); (*ppQueue)->Release(); } #ifdef NOT_YET
spQueue.Transfer(ppQueue); #endif // NOT_YET
hr = E_NOTIMPL; } } while (0); return hr; }
//+---------------------------------------------------------------------------
//
// Function: GetAndPrepareEnumeratorSlot
//
// Synopsis: Get an enumerator slot number from the command line.
//
// Arguments: [ppwsz] - command line
// [pidxSlot] - filled with slot number 0..NUM_ENUMERATOR_SLOTS-1
//
// Returns: S_OK - *[pidxSlot] is valid
// E_INVALIDARG - command line specified bad slot number
//
// Modifies: *pidxSlot
//
// History: 01-30-96 DavidMun Created
//
//----------------------------------------------------------------------------
HRESULT GetEnumeratorSlot(WCHAR **ppwsz, ULONG *pidxSlot) { HRESULT hr = S_OK;
do { hr = Expect(TKN_NUMBER, ppwsz, L"enumerator slot number"); BREAK_ON_FAILURE(hr);
if (g_ulLastNumberToken >= NUM_ENUMERATOR_SLOTS) { hr = E_INVALIDARG; g_Log.Write( LOG_ERROR, "got %u for enumerator slot, but value must be in 0..%u", g_ulLastNumberToken, NUM_ENUMERATOR_SLOTS - 1); break; }
*pidxSlot = g_ulLastNumberToken; } while (0); return hr; }
//+---------------------------------------------------------------------------
//
// Function: GetAndPrepareEnumeratorSlot
//
// Synopsis: Get an enumerator slot number from the command line, and
// release any existing enumerator at that slot.
//
// Arguments: [ppwsz] - command line
// [pidxSlot] - filled with slot number 0..NUM_ENUMERATOR_SLOTS-1
//
// Returns: S_OK - *[pidxSlot] is valid
// E_INVALIDARG - command line specified bad slot number
//
// Modifies: *pidxSlot, g_apEnumJob[*pidxSlot]
//
// History: 01-30-96 DavidMun Created
//
//----------------------------------------------------------------------------
HRESULT GetAndPrepareEnumeratorSlot(WCHAR **ppwsz, ULONG *pidxSlot) { HRESULT hr = S_OK;
do { hr = GetEnumeratorSlot(ppwsz, pidxSlot); BREAK_ON_FAILURE(hr);
//
// If there's an existing enumerator, get rid of it.
//
if (g_apEnumJobs[*pidxSlot]) { g_Log.Write( LOG_TRACE, "Releasing existing enumerator in slot %u", *pidxSlot); g_apEnumJobs[*pidxSlot]->Release(); g_apEnumJobs[*pidxSlot] = NULL; } } while (0); return hr; }
//+---------------------------------------------------------------------------
//
// Function: VerifySlotFilled
//
// Synopsis: Return S_OK if g_apEnumJob[idxSlot] contains a non-NULL
// pointer, E_INVALIDARG otherwise.
//
// History: 01-30-96 DavidMun Created
//
//----------------------------------------------------------------------------
HRESULT VerifySlotFilled(ULONG idxSlot) { if (!g_apEnumJobs[idxSlot]) { g_Log.Write( LOG_ERROR, "Slot %u does not contain an enumerator", idxSlot); return E_INVALIDARG; }
return S_OK; }
//+---------------------------------------------------------------------------
//
// Function: AddSeconds
//
// Synopsis: Add [ulSeconds] to [pst].
//
// Arguments: [pst] - valid systemtime
// [ulSeconds] - seconds to add
//
// Modifies: *[pst]
//
// History: 04-11-96 DavidMun Created
//
//----------------------------------------------------------------------------
VOID AddSeconds(SYSTEMTIME *pst, ULONG ulSeconds) { FILETIME ft; LONGLONG llTime; LONGLONG llIncrement;
//
// Convert caller's SYSTEMTIME to a FILETIME, which is easy to do math on.
//
SystemTimeToFileTime(pst, &ft);
//
// Convert the ulSeconds increment from seconds to 100 ns intervals, which
// is the unit used in the FILETIME struct.
//
llIncrement = ulSeconds; llIncrement *= 10000000UL;
//
// Convert the FILETIME equivalent of pst into a LONGLONG, then add the
// increment.
//
llTime = ft.dwHighDateTime; llTime <<= 32; llTime |= ft.dwLowDateTime; llTime += llIncrement;
//
// Convert the incremented LONGLONG back to a filetime, then convert that
// back to a SYSTEMTIME
//
ft.dwLowDateTime = (DWORD) llTime; ft.dwHighDateTime = (DWORD) (llTime >> 32); FileTimeToSystemTime(&ft, pst); }
|