//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1994 - 1996. // // File: jobprop.cxx // // Contents: Implementation of job property container class. // // History: 01-04-96 DavidMun Created // //---------------------------------------------------------------------------- #include #pragma hdrstop #include "jt.hxx" typedef HRESULT (STDMETHODCALLTYPE ITask::* SETSTRINGPROPFN)(LPCWSTR); typedef HRESULT (STDMETHODCALLTYPE ITask::* GETSTRINGPROPFN)(LPWSTR *); VOID SetStringProp( ITask *pJob, LPCSTR szMethodName, LPCWSTR wszNewValue, SETSTRINGPROPFN pfnSetJobStrProp, HRESULT *phr); VOID GetStringProp( ITask *pJob, LPCSTR szMethodName, GETSTRINGPROPFN pfnGetJobStrProp, WCHAR **ppwszProp, HRESULT *phr); #define JP_PRIORITY 0x0001 #define JP_MAXRUNTIME 0x0002 #define JP_IDLEWAIT 0x0004 #define JP_TASKFLAGS 0x0008 const ULONG MS_PER_SECOND = 1000; const ULONG MS_PER_MINUTE = 60 * MS_PER_SECOND; const ULONG MS_PER_HOUR = 60 * MS_PER_MINUTE; const ULONG MS_PER_DAY = 24 * MS_PER_HOUR; //+--------------------------------------------------------------------------- // // Member: CJobProp::CJobProp // // Synopsis: Init this. // // History: 01-08-96 DavidMun Created // // Notes: Note it is not safe to call Clear(), since it assumes any // non-NULL values in the string member vars are valid. // //---------------------------------------------------------------------------- CJobProp::CJobProp() { pwszAppName = NULL; pwszParams = NULL; pwszWorkingDirectory = NULL; pwszComment = NULL; pwszCreator = NULL; dwPriority = NORMAL_PRIORITY_CLASS; dwFlags = 0; } //+--------------------------------------------------------------------------- // // Member: CJobProp::~CJobProp // // Synopsis: Free resources // // History: 01-04-96 DavidMun Created // //---------------------------------------------------------------------------- CJobProp::~CJobProp() { Clear(); } //+--------------------------------------------------------------------------- // // Member: CJobProp::Clear // // Synopsis: Release all resources held by this and set all properties // to initial values. // // History: 01-04-96 DavidMun Created // //---------------------------------------------------------------------------- VOID CJobProp::Clear() { dwFlags = 0; dwPriority = NORMAL_PRIORITY_CLASS; dwMaxRunTime = 0; wIdleWait = 0; wIdleDeadline = 0; _flSet = 0; _flSetFlags = 0; CoTaskMemFree(pwszAppName); CoTaskMemFree(pwszParams); CoTaskMemFree(pwszWorkingDirectory); CoTaskMemFree(pwszComment); CoTaskMemFree(pwszCreator); pwszAppName = NULL; pwszParams = NULL; pwszWorkingDirectory = NULL; pwszComment = NULL; pwszCreator = NULL; ZeroMemory(&stMostRecentRun, sizeof stMostRecentRun); ZeroMemory(&stNextRun, sizeof stNextRun); dwExitCode = 0; hrStatus = 0; } //+--------------------------------------------------------------------------- // // Member: CJobProp::Dump // // Synopsis: Write job properties to the log // // History: 01-08-96 DavidMun Created // //---------------------------------------------------------------------------- VOID CJobProp::Dump() { g_Log.Write(LOG_TEXT, ""); g_Log.Write(LOG_TEXT, " ApplicationName: '%S'", pwszAppName); g_Log.Write(LOG_TEXT, " Parameters: '%S'", pwszParams); g_Log.Write(LOG_TEXT, " WorkingDirectory: '%S'", pwszWorkingDirectory); g_Log.Write(LOG_TEXT, " Comment: '%S'", pwszComment); g_Log.Write(LOG_TEXT, " Creator: '%S'", pwszCreator); g_Log.Write(LOG_TEXT, " Priority: %s", GetPriorityString(dwPriority)); if (dwMaxRunTime == INFINITE) { g_Log.Write(LOG_TEXT, " MaxRunTime: INFINITE"); } else { ULONG ulMRT = dwMaxRunTime; ULONG ulDays = ulMRT / MS_PER_DAY; ulMRT %= MS_PER_DAY; ULONG ulHours = ulMRT / MS_PER_HOUR; ulMRT %= MS_PER_HOUR; ULONG ulMinutes = ulMRT / MS_PER_MINUTE; ulMRT %= MS_PER_MINUTE; ULONG ulSeconds = (ulMRT + MS_PER_SECOND / 2) / MS_PER_SECOND; g_Log.Write( LOG_TEXT, " MaxRunTime: %u (%ud %2u:%02u:%02u)", dwMaxRunTime, ulDays, ulHours, ulMinutes, ulSeconds); } g_Log.Write(LOG_TEXT, " IdleWait: %u", wIdleWait); g_Log.Write(LOG_TEXT, " IdleDeadline: %u", wIdleDeadline); g_Log.Write(LOG_TEXT, " MostRecentRun: %02u/%02u/%04u %2u:%02u:%02u", stMostRecentRun.wMonth, stMostRecentRun.wDay, stMostRecentRun.wYear, stMostRecentRun.wHour, stMostRecentRun.wMinute, stMostRecentRun.wSecond); g_Log.Write(LOG_TEXT, " NextRun: %02u/%02u/%04u %2u:%02u:%02u", stNextRun.wMonth, stNextRun.wDay, stNextRun.wYear, stNextRun.wHour, stNextRun.wMinute, stNextRun.wSecond); g_Log.Write(LOG_TEXT, " StartError: %s", GetStatusString(hrStartError)); g_Log.Write(LOG_TEXT, " ExitCode: %#x", dwExitCode); g_Log.Write(LOG_TEXT, " Status: %s", GetStatusString(hrStatus)); g_Log.Write(LOG_TEXT, " ScheduledWorkItem Flags:"); DumpJobFlags(dwFlags); g_Log.Write(LOG_TEXT, " TaskFlags: %#x", dwTaskFlags); } //+--------------------------------------------------------------------------- // // Member: CJobProp::Parse // // Synopsis: Set this object's members according to the values specified // on the command line. // // Arguments: [ppwsz] - command line. // // Returns: S_OK - this valid // E_* - error logged // // History: 01-03-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT CJobProp::Parse(WCHAR **ppwsz) { HRESULT hr = S_OK; TOKEN tkn; TOKEN tknProp; WCHAR *pwszStringValue; Clear(); tkn = PeekToken(ppwsz); while (tkn != TKN_SWITCH && tkn != TKN_EOL && tkn != TKN_INVALID) { // // Get the property name token in tknProp, then eat the equal sign // and, depending on the property, get a string, token or number // value. // tknProp = GetToken(ppwsz); hr = Expect(TKN_EQUAL, ppwsz, L"="); BREAK_ON_FAILURE(hr); if (tknProp == TKN_WORKINGDIRECTORY) { hr = GetFilename(ppwsz, L"filename"); if (SUCCEEDED(hr)) { hr = DupString(g_wszLastStringToken, &pwszStringValue); } } else if (tknProp == TKN_APPNAME || tknProp == TKN_PARAMS || tknProp == TKN_COMMENT || tknProp == TKN_CREATOR) { hr = Expect(TKN_STRING, ppwsz, L"string property value"); if (SUCCEEDED(hr)) { hr = DupString(g_wszLastStringToken, &pwszStringValue); } } else if (tknProp == TKN_PRIORITY) { tkn = GetToken(ppwsz); } else { hr = Expect(TKN_NUMBER, ppwsz, L"numeric property value"); } BREAK_ON_FAILURE(hr); // // Now assign the value to the appropriate member // switch (tknProp) { case TKN_APPNAME: pwszAppName = pwszStringValue; break; case TKN_PARAMS: pwszParams = pwszStringValue; break; case TKN_WORKINGDIRECTORY: pwszWorkingDirectory = pwszStringValue; break; case TKN_COMMENT: pwszComment = pwszStringValue; break; case TKN_CREATOR: pwszCreator = pwszStringValue; break; case TKN_PRIORITY: _flSet |= JP_PRIORITY; switch (tkn) { case TKN_IDLE: // used here as priority dwPriority = IDLE_PRIORITY_CLASS; break; case TKN_NORMAL: dwPriority = NORMAL_PRIORITY_CLASS; break; case TKN_HIGH: dwPriority = HIGH_PRIORITY_CLASS; break; case TKN_REALTIME: dwPriority = REALTIME_PRIORITY_CLASS; break; default: hr = E_FAIL; LogSyntaxError(tkn, L"IDLE, NORMAL, HIGH, or REALTIME"); } break; case TKN_MAXRUNTIME: _flSet |= JP_MAXRUNTIME; dwMaxRunTime = g_ulLastNumberToken; break; case TKN_IDLE: // used here as idlewait/deadline property _flSet |= JP_IDLEWAIT; wIdleWait = (WORD)g_ulLastNumberToken; hr = Expect(TKN_NUMBER, ppwsz, L"idle deadline"); BREAK_ON_FAILURE(hr); wIdleDeadline = (WORD)g_ulLastNumberToken; break; case TKN_TASKFLAGS: _flSet |= JP_TASKFLAGS; dwTaskFlags = g_ulLastNumberToken; break; #ifndef RES_KIT case TKN_INTERACTIVE: _flSetFlags |= TASK_FLAG_INTERACTIVE; if (g_ulLastNumberToken) { dwFlags |= TASK_FLAG_INTERACTIVE; } break; #endif case TKN_DONTRUNONBATTERIES: _flSetFlags |= TASK_FLAG_DONT_START_IF_ON_BATTERIES; if (g_ulLastNumberToken) { dwFlags |= TASK_FLAG_DONT_START_IF_ON_BATTERIES; } break; case TKN_KILLIFGOINGONBATS: _flSetFlags |= TASK_FLAG_KILL_IF_GOING_ON_BATTERIES; if (g_ulLastNumberToken) { dwFlags |= TASK_FLAG_KILL_IF_GOING_ON_BATTERIES; } break; case TKN_RUNONLYIFLOGGEDON: _flSetFlags |= TASK_FLAG_RUN_ONLY_IF_LOGGED_ON; if (g_ulLastNumberToken) { dwFlags |= TASK_FLAG_RUN_ONLY_IF_LOGGED_ON; } break; case TKN_SYSTEMREQUIRED: _flSetFlags |= TASK_FLAG_SYSTEM_REQUIRED; if (g_ulLastNumberToken) { dwFlags |= TASK_FLAG_SYSTEM_REQUIRED; } break; case TKN_DELETEWHENDONE: _flSetFlags |= TASK_FLAG_DELETE_WHEN_DONE; if (g_ulLastNumberToken) { dwFlags |= TASK_FLAG_DELETE_WHEN_DONE; } break; case TKN_SUSPEND: _flSetFlags |= TASK_FLAG_DISABLED; if (g_ulLastNumberToken) { dwFlags |= TASK_FLAG_DISABLED; } break; case TKN_ONLYIFIDLE: _flSetFlags |= TASK_FLAG_START_ONLY_IF_IDLE; if (g_ulLastNumberToken) { dwFlags |= TASK_FLAG_START_ONLY_IF_IDLE; } break; case TKN_KILLATIDLEEND: _flSetFlags |= TASK_FLAG_KILL_ON_IDLE_END; if (g_ulLastNumberToken) { dwFlags |= TASK_FLAG_KILL_ON_IDLE_END; } break; case TKN_RESTARTONIDLERESUME: _flSetFlags |= TASK_FLAG_RESTART_ON_IDLE_RESUME; if (g_ulLastNumberToken) { dwFlags |= TASK_FLAG_RESTART_ON_IDLE_RESUME; } break; case TKN_HIDDEN: _flSetFlags |= TASK_FLAG_HIDDEN; if (g_ulLastNumberToken) { dwFlags |= TASK_FLAG_HIDDEN; } break; default: hr = E_FAIL; LogSyntaxError(tknProp, L"job property name"); break; } tkn = PeekToken(ppwsz); } return hr; } //+--------------------------------------------------------------------------- // // Member: CJobProp::InitFromActual // // Synopsis: Read properties from [pJob] and set this object to match // // Arguments: [pJob] - job object whose properties we'll read // // Returns: S_OK - this initialized // E_* - error logged, this only partly initialized // // History: 01-08-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT CJobProp::InitFromActual(ITask *pJob) { HRESULT hr = S_OK; do { Clear(); hr = pJob->GetApplicationName(&pwszAppName); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetApplicationName(&pwszAppName)"); CoTaskMemFree(pwszAppName); GetStringProp(pJob, "ApplicationName", &ITask::GetApplicationName, &pwszAppName, &hr); GetStringProp(pJob, "Parameters", &ITask::GetParameters, &pwszParams, &hr); GetStringProp(pJob, "WorkingDirectory", &ITask::GetWorkingDirectory, &pwszWorkingDirectory, &hr); GetStringProp(pJob, "Comment", &ITask::GetComment, &pwszComment, &hr); GetStringProp(pJob, "Creator", &ITask::GetCreator, &pwszCreator, &hr); BREAK_ON_FAILURE(hr); hr = pJob->GetPriority(&dwPriority); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetPriority"); hr = pJob->GetMaxRunTime(&dwMaxRunTime); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetMaxRunTime"); hr = pJob->GetIdleWait(&wIdleWait, &wIdleDeadline); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetIdleWait"); hr = pJob->GetFlags(&dwFlags); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetFlags"); hr = pJob->GetTaskFlags(&dwTaskFlags); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetTaskFlags"); hr = pJob->GetMostRecentRunTime(&stMostRecentRun); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetMostRecentRunTime"); hr = pJob->GetNextRunTime(&stNextRun); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetNextRunTime"); hrStartError = pJob->GetExitCode(&dwExitCode); hr = pJob->GetStatus(&hrStatus); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetStatus"); } while (0); return hr; } //+--------------------------------------------------------------------------- // // Member: CJobProp::SetActual // // Synopsis: Set the properties of the job object with interface [pJob] // to the ones stored in this. // // Arguments: [pJob] - ITask interface // // Returns: S_OK - all props set // E_* - error logged // // History: 01-08-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT CJobProp::SetActual(ITask *pJob) { HRESULT hr = S_OK; HRESULT hrReturn = S_OK; ULONG flCurFlags; SetStringProp(pJob, "ApplicationName", pwszAppName, &ITask::SetApplicationName, &hrReturn); SetStringProp(pJob, "Parameters", pwszParams, &ITask::SetParameters, &hrReturn); SetStringProp(pJob, "WorkingDirectory", pwszWorkingDirectory, &ITask::SetWorkingDirectory, &hrReturn); SetStringProp(pJob, "Comment", pwszComment , &ITask::SetComment , &hrReturn); SetStringProp(pJob, "Creator", pwszCreator, &ITask::SetCreator, &hrReturn); if (_flSet & JP_PRIORITY) { hr = pJob->SetPriority(dwPriority); if (FAILED(hr)) { g_Log.Write( LOG_FAIL, "ITask::SetPriority(%u) hr=%#010x", dwPriority, hr); hrReturn = hr; } } if (_flSet & JP_MAXRUNTIME) { hr = pJob->SetMaxRunTime(dwMaxRunTime); if (FAILED(hr)) { g_Log.Write( LOG_FAIL, "ITask::SetMaxRunTime(%u) hr=%#010x", dwMaxRunTime, hr); hrReturn = hr; } } if (_flSet & JP_IDLEWAIT) { hr = pJob->SetIdleWait(wIdleWait, wIdleDeadline); if (FAILED(hr)) { g_Log.Write( LOG_FAIL, "ITask::SetIdleWait(%u,%u) hr=%#010x", wIdleWait, wIdleDeadline, hr); hrReturn = hr; } } if (_flSet & JP_TASKFLAGS) { hr = pJob->SetTaskFlags(dwTaskFlags); if (FAILED(hr)) { g_Log.Write( LOG_FAIL, "ITask::SetTaskFlags(%u) hr=%#010x", dwTaskFlags, hr); hrReturn = hr; } } hr = pJob->GetFlags(&flCurFlags); if (SUCCEEDED(hr)) { // // Turn off all flags user touched, then turn back on ones // he specified nonzero value for. // flCurFlags &= ~_flSetFlags; flCurFlags |= dwFlags; hr = pJob->SetFlags(flCurFlags); if (FAILED(hr)) { g_Log.Write(LOG_FAIL, "ITask::SetFlags hr=%#010x", hr); hrReturn = hr; } } else { g_Log.Write(LOG_FAIL, "ITask::GetFlags hr=%#010x", hr); hrReturn = hr; } return hrReturn; } //+--------------------------------------------------------------------------- // // Function: SetStringProp // // Synopsis: Set a string property on a job object // // Arguments: [pJob] - job object to modify // [szMethodName] - for logging, name of method we're calling // [wszNewValue] - new string value for property // [pfnSetJobStrProp] - ITask member function pointer // [phr] - filled with error if failure occurs // // Modifies: *[phr] on error // // History: 01-05-96 DavidMun Created // //---------------------------------------------------------------------------- VOID SetStringProp( ITask *pJob, LPCSTR szMethodName, LPCWSTR wszNewValue, SETSTRINGPROPFN pfnSetJobStrProp, HRESULT *phr) { HRESULT hr = S_OK; if (wszNewValue) { hr = (pJob->*pfnSetJobStrProp)(wszNewValue); if (hr == E_NOTIMPL) { g_Log.Write( LOG_WARN, "Ignoring E_NOTIMPL from ITask::Set%s", szMethodName); } else if (FAILED(hr)) { g_Log.Write(LOG_FAIL, "ITask::Set%s hr=%#010x", szMethodName, hr); *phr = hr; } } } //+--------------------------------------------------------------------------- // // Function: GetStringProp // // Synopsis: Read a string property from a job object // // Arguments: [pJob] - object from which to read property // [szMethodName] - for logging, name of method to call // [pfnGetJobStrProp] - pointer to ITask method to call // [ppwszProp] - filled with new'd string // [phr] - modified on error // // Modifies: *[phr] on error // // History: 01-05-96 DavidMun Created // //---------------------------------------------------------------------------- VOID GetStringProp( ITask *pJob, LPCSTR szMethodName, GETSTRINGPROPFN pfnGetJobStrProp, WCHAR **ppwszProp, HRESULT *phr) { HRESULT hr = S_OK; UINT cchProp; do { hr = (pJob->*pfnGetJobStrProp)(ppwszProp); if (hr == E_NOTIMPL) { g_Log.Write( LOG_WARN, "Ignoring E_NOTIMPL from ITask::Get%s", szMethodName); hr = S_OK; break; } if (FAILED(hr)) { g_Log.Write( LOG_FAIL, "ITask::Get%s(ppwszProp) hr=%#010x", szMethodName, hr); } } while (0); if (FAILED(hr)) { *phr = hr; } }