//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1994 - 1996. // // File: commands.cxx // // Contents: Implementation of command-line switches. // // History: 01-03-96 DavidMun Created // //---------------------------------------------------------------------------- #include #pragma hdrstop #include "jt.hxx" #include "..\..\inc\defines.hxx" #define MAX_TRIGGER_STRING 160 #define DEFAULT_FETCH_COUNT 2 #define MSTASK_DLL TEXT("MSTASK.DLL") typedef HRESULT (WINAPI * PSETNSACCOUNTINFO)(LPCWSTR, LPCWSTR, LPCWSTR); typedef HRESULT (WINAPI * PGETNSACCOUNTINFO)(LPCWSTR, DWORD, LPWSTR); //+--------------------------------------------------------------------------- // // Function: Abort // // Synopsis: Parse and execute the abort job command. // // Arguments: [ppwsz] - command line // [fJob] - TRUE=>operate on job, FALSE=>operate on queue // // Returns: S_OK - command executed // E_* - error logged // // Modifies: *[ppwsz] // // History: 01-05-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT Abort(WCHAR **ppwsz, BOOL fJob) { HRESULT hr = S_OK; if (fJob) { g_Log.Write(LOG_TRACE, "Aborting job"); hr = g_pJob->Terminate(); if (FAILED(hr)) { g_Log.Write(LOG_FAIL, "ITask::Terminate hr=%#010x", hr); } } else { g_Log.Write(LOG_TRACE, "Aborting Queue"); #ifdef NOT_YET hr = g_pJobQueue->Terminate(); if (FAILED(hr)) { g_Log.Write(LOG_FAIL, "ITaskQueue::Terminate hr=%#010x", hr); } #endif // NOT_YET hr = E_NOTIMPL; } return hr; } //+--------------------------------------------------------------------------- // // Function: ConvertSage // // Synopsis: Execute the convert sage tasks to jobs command, but only // if this binary was built for and is running on Win9x. // // Returns: Built for or runnong on NT - S_OK // Otherwise - result of ConvertSageTasksToJobs() // // History: 03-25-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT ConvertSage() { HRESULT hr = S_OK; #ifdef _CHICAGO_ OSVERSIONINFO VersionInfo = { sizeof OSVERSIONINFO }; GetVersionEx(&VersionInfo); if (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { hr = ConvertSageTasksToJobs(); } else { g_Log.Write( LOG_WARN, "This command cannot be executed when running under Windows NT."); } #else g_Log.Write( LOG_WARN, "This version of JT was built for NT and cannot execute this command."); #endif // !_CHICAGO_ return hr; } //+--------------------------------------------------------------------------- // // Function: SetNSAccountInfo // // Synopsis: // // Returns: // // History: // //---------------------------------------------------------------------------- HRESULT SetNSAccountInfo(WCHAR ** ppwsz) { #define SET_NS_ACCOUNT_INFO "SetNetScheduleAccountInformation" HRESULT hr = S_OK; #ifndef _CHICAGO_ OSVERSIONINFO VersionInfo = { sizeof OSVERSIONINFO }; GetVersionEx(&VersionInfo); if (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) { WCHAR wszAccount[MAX_USERNAME + 1]; WCHAR wszPassword[MAX_PASSWORD + 1]; hr = Expect(TKN_STRING, ppwsz, L"Account name"); if (FAILED(hr)) { return hr; } wcsncpy(wszAccount, g_wszLastStringToken, min(wcslen(g_wszLastStringToken) + 1, MAX_USERNAME)); hr = Expect(TKN_STRING, ppwsz, L"Account password"); if (FAILED(hr)) { return hr; } wcsncpy(wszPassword, g_wszLastStringToken, min(wcslen(g_wszLastStringToken) + 1, MAX_PASSWORD)); PSETNSACCOUNTINFO pSetNSAccountInfo; HMODULE hMod = LoadLibrary(MSTASK_DLL); if (hMod == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); g_Log.Write(LOG_FAIL, "LoadLibrary hr=%#010x", hr); return hr; } else { pSetNSAccountInfo = (PSETNSACCOUNTINFO)GetProcAddress( hMod, SET_NS_ACCOUNT_INFO); if (pSetNSAccountInfo == NULL) { FreeLibrary(hMod); hr = HRESULT_FROM_WIN32(GetLastError()); g_Log.Write(LOG_FAIL, "GetProcAddress hr=%#010x", hr); return hr; } } hr = pSetNSAccountInfo( NULL, lstrcmpiW(wszAccount, L"NULL") == 0 ? NULL : wszAccount, wszPassword); if (FAILED(hr)) { g_Log.Write(LOG_FAIL, "SetNetScheduleAccountInformation hr=%#010x", hr); } FreeLibrary(hMod); } else { g_Log.Write( LOG_WARN, "This command cannot be executed when running under Windows 95."); } #else g_Log.Write( LOG_WARN, "This version of JT was built for Win95 and cannot execute this command."); #endif // !_CHICAGO_ return hr; } //+--------------------------------------------------------------------------- // // Function: PrintNSAccountInfo // // Synopsis: // // Returns: // // History: // //---------------------------------------------------------------------------- HRESULT PrintNSAccountInfo(void) { #define GET_NS_ACCOUNT_INFO "GetNetScheduleAccountInformation" HRESULT hr = S_OK; #ifndef _CHICAGO_ OSVERSIONINFO VersionInfo = { sizeof OSVERSIONINFO }; GetVersionEx(&VersionInfo); if (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) { PGETNSACCOUNTINFO pGetNSAccountInfo; HMODULE hMod = LoadLibrary(MSTASK_DLL); if (hMod == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); g_Log.Write(LOG_FAIL, "LoadLibrary hr=%#010x", hr); return hr; } else { pGetNSAccountInfo = (PGETNSACCOUNTINFO)GetProcAddress( hMod, GET_NS_ACCOUNT_INFO); if (pGetNSAccountInfo == NULL) { FreeLibrary(hMod); hr = HRESULT_FROM_WIN32(GetLastError()); g_Log.Write(LOG_FAIL, "GetProcAddress hr=%#010x", hr); return hr; } } WCHAR wszAccount[MAX_USERNAME + 1]; DWORD ccAccount = MAX_USERNAME + 1; hr = pGetNSAccountInfo(NULL, ccAccount, wszAccount); if (SUCCEEDED(hr)) { if (hr == S_FALSE) { g_Log.Write(LOG_TRACE, "NetSchedule account not specified"); } else { g_Log.Write(LOG_TRACE, "NetSchedule account name = '%S'", wszAccount); } } else { g_Log.Write(LOG_FAIL, "GetNetScheduleAccountInformation hr=%#010x", hr); } FreeLibrary(hMod); } else { g_Log.Write( LOG_WARN, "This command cannot be executed when running under Windows 95."); } #else g_Log.Write( LOG_WARN, "This version of JT was built for Win95 and cannot execute this command."); #endif // !_CHICAGO_ return hr; } //+--------------------------------------------------------------------------- // // Function: CreateTrigger // // Synopsis: Parse and execute the create trigger command. // // Arguments: [ppwsz] - command line // // Returns: S_OK - created trigger // E_* - error logged // // History: 01-04-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT CreateTrigger(WCHAR **ppwsz, BOOL fJob) { HRESULT hr = S_OK; CTrigProp TriggerProps; USHORT usTrigger; SpIJobTrigger spTrigger; do { hr = TriggerProps.Parse(ppwsz); BREAK_ON_FAILURE(hr); // // Ask job or queue to create trigger // if (fJob) { hr = g_pJob->CreateTrigger(&usTrigger, &spTrigger); LOG_AND_BREAK_ON_FAIL(hr, "ITask::CreateTrigger"); } else { #ifdef NOT_YET hr = g_pJobQueue->CreateTrigger(&usTrigger, &spTrigger); LOG_AND_BREAK_ON_FAIL(hr, "ITaskQueue::CreateTrigger"); #endif // NOT_YET hr = E_NOTIMPL; } g_Log.Write(LOG_TRACE, "Created trigger %u", usTrigger); // // Now set the trigger's properties to the values we parsed already // hr = TriggerProps.SetActual(spTrigger); } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: DeleteTrigger // // Synopsis: Parse and execute the delete trigger command. // // Arguments: [ppwsz] - command line // // Returns: S_OK - trigger deleted // E_* - error logged // // Modifies: *[ppwsz] // // History: 01-05-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT DeleteTrigger(WCHAR **ppwsz, BOOL fJob) { HRESULT hr = S_OK; USHORT usTrigger = 0; do { if (PeekToken(ppwsz) == TKN_NUMBER) { GetToken(ppwsz); usTrigger = (SHORT) g_ulLastNumberToken; } g_Log.Write(LOG_TRACE, "Deleting trigger %u", usTrigger); if (fJob) { hr = g_pJob->DeleteTrigger(usTrigger); LOG_AND_BREAK_ON_FAIL(hr, "ITask::DeleteTrigger"); } else { #ifdef NOT_YET hr = g_pJobQueue->DeleteTrigger(usTrigger); LOG_AND_BREAK_ON_FAIL(hr, "ITaskQueue::DeleteTrigger"); #endif // NOT_YET hr = E_NOTIMPL; } } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: EditJob // // Synopsis: Invoke the edit job command // // Arguments: [ppwsz] - command line // [fJob] - TRUE=>edit g_pJob, FALSE=>edit a job in g_pJobQueue // // Returns: S_OK - UI invoked // E_* - error logged // // History: 01-11-96 DavidMun Created // 06-28-96 DavidMun Support individual prop pages // //---------------------------------------------------------------------------- HRESULT EditJob(WCHAR **ppwsz, BOOL fJob) { HRESULT hr = S_OK; SpIJob spJob; ITask *pJob; // Do not Release this SpIUnknown spunkJob; SpIProvideTaskPage spProvideTaskPage; TOKEN tkn; ULONG ulType = 0; BOOL fPersist = TRUE; PROPSHEETHEADER psh; HPROPSHEETPAGE hPage; LONG lResult; ZeroMemory(&psh, sizeof(psh)); do { if (fJob) { pJob = g_pJob; } else { #ifdef NOT_YET hr = Expect(TKN_STRING, ppwsz, L"job name"); BREAK_ON_FAILURE(hr); hr = g_pJobQueue->GetTask( g_wszLastStringToken, IID_IUnknown, &spunkJob); LOG_AND_BREAK_ON_FAIL(hr, "ITaskQueue::GetTask"); hr = spunkJob->QueryInterface(IID_ITask, (VOID**)(ITask**)&spJob); LOG_AND_BREAK_ON_FAIL(hr, "QI for ITask"); pJob = spJob; #endif // NOT_YET hr = E_NOTIMPL; } // // See if the optional property sheet page argument has been // specified. If so, retrieve and open just that page, otherwise use // the EditJob method to open all the pages. // tkn = PeekToken(ppwsz); if (tkn == TKN_NUMBER) { GetToken(ppwsz); ulType = g_ulLastNumberToken; // // Now see if the optional value for fPersistChanges was // provided. // tkn = PeekToken(ppwsz); if (tkn == TKN_STRING) { GetToken(ppwsz); fPersist = g_wszLastStringToken[0] == L't' || g_wszLastStringToken[0] == L'T'; } // // Get the interface that has the method that returns a page. // Then retrieve the page the user asked for. // hr = pJob->QueryInterface( IID_IProvideTaskPage, (VOID**)(IProvideTaskPage**)&spProvideTaskPage); LOG_AND_BREAK_ON_FAIL(hr, "QI for IProvideTaskPage"); g_Log.Write( LOG_TRACE, "Opening page %u, changes will%s be persisted", ulType, fPersist ? "" : " not"); hr = spProvideTaskPage->GetPage((TASKPAGE)ulType, fPersist, &hPage); LOG_AND_BREAK_ON_FAIL(hr, "IProvideTaskPage::GetPage"); // // Now that we have the page, display it in its very own // property sheet. // psh.dwSize = sizeof(PROPSHEETHEADER); psh.dwFlags = PSH_DEFAULT; psh.hwndParent = NULL; psh.hInstance = NULL; psh.pszCaption = TEXT("jt job object"); psh.phpage = &hPage; psh.nPages = 1; lResult = PropertySheet(&psh); if (lResult == -1) { g_Log.Write(LOG_FAIL, "PropertySheet (%u)", GetLastError()); hr = HRESULT_FROM_WIN32(GetLastError()); } } else { hr = pJob->EditWorkItem(NULL, TRUE); LOG_AND_BREAK_ON_FAIL(hr, "ITask::EditWorkItem"); } } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: EnumClone // // Synopsis: Invoke the IEnumJobs::Clone command // // Arguments: [ppwsz] - command line // // Returns: S_OK - a slot has been filled with cloned enumerator // E_INVALIDARG - bad slot number // // Modifies: g_apEnumJobs // // History: 01-30-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT EnumClone(WCHAR **ppwsz) { HRESULT hr = S_OK; ULONG idxDestSlot; ULONG idxSourceSlot; do { hr = GetAndPrepareEnumeratorSlot(ppwsz, &idxDestSlot); BREAK_ON_FAILURE(hr); hr = GetEnumeratorSlot(ppwsz, &idxSourceSlot); BREAK_ON_FAILURE(hr); hr = VerifySlotFilled(idxSourceSlot); BREAK_ON_FAILURE(hr); g_Log.Write( LOG_TRACE, "Cloning enumerator in slot %u into slot %u", idxSourceSlot, idxDestSlot); hr = g_apEnumJobs[idxSourceSlot]->Clone(&g_apEnumJobs[idxDestSlot]); if (FAILED(hr)) { g_Log.Write( LOG_FAIL, "IEnumJobs::Clone hr=%#010x", hr); } } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: EnumNext // // Synopsis: Invoke the IEnumJobs::Next command // // Arguments: [ppwsz] - command line // // Returns: S_OK - Next performed successfully // E_INVALIDARG - bad slot number // // History: 01-30-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT EnumNext(WCHAR **ppwsz) { HRESULT hr = S_OK; ULONG idxSlot; LPWSTR *ppwszFetched; LPWSTR *ppwszCur; ULONG cFetched; ULONG i; do { hr = GetEnumeratorSlot(ppwsz, &idxSlot); BREAK_ON_FAILURE(hr); hr = VerifySlotFilled(idxSlot); BREAK_ON_FAILURE(hr); hr = Expect(TKN_NUMBER, ppwsz, L"number of items to enumerate"); BREAK_ON_FAILURE(hr); g_Log.Write( LOG_TRACE, "Enumerating next %u items using enumerator in slot %u", g_ulLastNumberToken, idxSlot); hr = g_apEnumJobs[idxSlot]->Next(g_ulLastNumberToken, &ppwszFetched, &cFetched); LOG_AND_BREAK_ON_FAIL(hr, "IEnumJobs::Next"); if (hr == S_FALSE) { g_Log.Write(LOG_INFO, "IEnumJobs::Next returned S_FALSE"); } if (cFetched != g_ulLastNumberToken) { g_Log.Write( LOG_INFO, "IEnumJobs::Next fetched only %u jobs", cFetched); } for (i = 0, ppwszCur = ppwszFetched; i < cFetched; i++, ppwszCur++) { g_Log.Write(LOG_TEXT, "%u: %S", idxSlot, *ppwszCur); CoTaskMemFree(*ppwszCur); } CoTaskMemFree(ppwszFetched); } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: EnumReset // // Synopsis: Invoke the IEnumJobs::Reset command // // Arguments: [ppwsz] - command line // // Returns: S_OK - Reset performed successfully // E_INVALIDARG - bad slot number // // History: 01-30-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT EnumReset(WCHAR **ppwsz) { HRESULT hr = S_OK; ULONG idxSlot; do { hr = GetEnumeratorSlot(ppwsz, &idxSlot); BREAK_ON_FAILURE(hr); hr = VerifySlotFilled(idxSlot); BREAK_ON_FAILURE(hr); g_Log.Write(LOG_TRACE, "Resetting enumerator in slot %u", idxSlot); hr = g_apEnumJobs[idxSlot]->Reset(); LOG_AND_BREAK_ON_FAIL(hr, "IEnumJobs::Reset"); } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: EnumSkip // // Synopsis: Invoke the IEnumJobs::Skip command // // Arguments: [ppwsz] - command line // // Returns: S_OK - Skip performed successfully // E_INVALIDARG - bad slot number // // History: 01-30-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT EnumSkip(WCHAR **ppwsz) { HRESULT hr = S_OK; ULONG idxSlot; do { hr = GetEnumeratorSlot(ppwsz, &idxSlot); BREAK_ON_FAILURE(hr); hr = VerifySlotFilled(idxSlot); BREAK_ON_FAILURE(hr); hr = Expect(TKN_NUMBER, ppwsz, L"number of items to skip"); BREAK_ON_FAILURE(hr); g_Log.Write( LOG_TRACE, "Skipping next %u items using enumerator in slot %u", g_ulLastNumberToken, idxSlot); hr = g_apEnumJobs[idxSlot]->Skip(g_ulLastNumberToken); LOG_AND_BREAK_ON_FAIL(hr, "IEnumJobs::Skip"); if (hr == S_FALSE) { g_Log.Write(LOG_INFO, "IEnumJobs::Skip returned S_FALSE"); } } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: Load // // Synopsis: Load the job or queue file specified on the command line // into the global job or queue object. // // Arguments: [ppwsz] - command line. // [szJobOrQueue] - "Job" or "Queue" // [fJob] - TRUE=>use global job, FALSE=>use global queue // // Returns: S_OK - job or queue loaded // E_* - error logged // // History: 01-10-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT Load(WCHAR **ppwsz, CHAR *szJobOrQueue, BOOL fJob) { HRESULT hr = S_OK; SpIPersistFile spPersistFile; do { hr = GetFilename(ppwsz, L"file to load"); BREAK_ON_FAILURE(hr); g_Log.Write( LOG_TRACE, "Loading %s %S", szJobOrQueue, g_wszLastStringToken); if (fJob) { g_pJob->QueryInterface( IID_IPersistFile, (VOID**)(IPersistFile**)&spPersistFile); LOG_AND_BREAK_ON_FAIL(hr, "ITask::QI(IPersistFile)"); } else { g_pJobQueue->QueryInterface( IID_IPersistFile, (VOID**)(IPersistFile**)&spPersistFile); LOG_AND_BREAK_ON_FAIL(hr, "ITaskQueue::QI(IPersistFile)"); } DWORD ulTicks = GetTickCount(); hr = spPersistFile->Load( g_wszLastStringToken, STGM_READWRITE | STGM_SHARE_EXCLUSIVE); ulTicks = GetTickCount() - ulTicks; g_Log.Write(LOG_PERF, "Load took %lu ms", ulTicks); LOG_AND_BREAK_ON_FAIL(hr, "IPersistFile::Load"); } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: PrintAll // // Synopsis: Print all properties of global job or queue. // // Arguments: [ppwsz] - command line // [fJob] - TRUE=>use global job, FALSE=>use global queue // // Returns: S_OK - command executed // E_* - error logged // // Modifies: *[ppwsz] // // History: 01-10-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT PrintAll(WCHAR **ppwsz, BOOL fJob) { HRESULT hr = S_OK; do { if (!fJob) { g_Log.Write(LOG_ERROR, "this command is not yet implemented"); break; } else { hr = DumpJob(g_pJob); BREAK_ON_FAILURE(hr); hr = DumpJobTriggers(g_pJob); } } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: PrintRunTimes // // Synopsis: Parse and execute the print job run times command // // Arguments: [ppwsz] - command line // [fJob] - TRUE=>use global job, FALSE=>use global queue // // Returns: S_OK - command executed // E_* - error logged // // Modifies: *[ppwsz] // // History: 01-05-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT PrintRunTimes(WCHAR **ppwsz, BOOL fJob) { HRESULT hr = S_OK; TOKEN tkn; USHORT cRuns = 0; SYSTEMTIME stNow; LPSYSTEMTIME pstRuns = NULL; USHORT i; do { tkn = PeekToken(ppwsz); if (tkn == TKN_NUMBER) { GetToken(ppwsz); cRuns = (USHORT) g_ulLastNumberToken; } GetLocalTime(&stNow); // // If the optional number of runs was not specified or was 0, // print remaining runs for today only. // if (cRuns == 0) { SYSTEMTIME stEnd; stEnd = stNow; stEnd.wHour = 23; stEnd.wMinute = 59; if (fJob) { hr = g_pJob->GetRunTimes(&stNow, &stEnd, &cRuns, &pstRuns); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetRunTimes"); } else { #ifdef NOT_YET hr = g_pJobQueue->GetRunTimes(&stNow, &stEnd, &cRuns, &pstRuns); LOG_AND_BREAK_ON_FAIL(hr, "ITaskQueue::GetRunTimes"); #endif // NOT_YET hr = E_NOTIMPL; } if (cRuns == 0) { g_Log.Write(LOG_TEXT, "No runs are scheduled for today."); break; } g_Log.Write(LOG_TEXT, "The remaining %u run", cRuns); g_Log.Write(LOG_TEXT, "times for today:"); g_Log.Write(LOG_TEXT, "--------------------"); } else { // // cRuns > 0. Get at most the next cRuns run times. // if (fJob) { hr = g_pJob->GetRunTimes(&stNow, NULL, &cRuns, &pstRuns); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetRunTimes"); } else { #ifdef NOT_YET hr = g_pJobQueue->GetRunTimes(&stNow, NULL, &cRuns, &pstRuns); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetRunTimes"); #endif // NOT_YET hr = E_NOTIMPL; } if (cRuns == 0) { g_Log.Write(LOG_TEXT, "No runs are scheduled. hr = %#lx", hr); break; } g_Log.Write(LOG_TEXT, "ITask::GetRunTimes succeeded, hr = %#lx", hr); g_Log.Write(LOG_TEXT, "The next %u run times:", cRuns); g_Log.Write(LOG_TEXT, "----------------------"); } for (i = 0; i < cRuns; i++) { g_Log.Write( LOG_TEXT, "%02d/%02d/%d at %02d:%02d:%02d", pstRuns[i].wMonth, pstRuns[i].wDay, pstRuns[i].wYear, pstRuns[i].wHour, pstRuns[i].wMinute, pstRuns[i].wSecond); } } while (0); CoTaskMemFree(pstRuns); return hr; } //+--------------------------------------------------------------------------- // // Function: PrintTrigger // // Synopsis: Print one or more trigger's properties // // Arguments: [ppwsz] - command line // [fJob] - TRUE=>use g_pJob, FALSE=>use g_pJobQueue // // Returns: S_OK - trigger(s) printed // E_* - error logged // // History: 01-10-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT PrintTrigger(WCHAR **ppwsz, BOOL fJob) { HRESULT hr = S_OK; USHORT usTrigger = 0; BOOL fPrintAll = FALSE; SpIJobTrigger spTrigger; do { if (PeekToken(ppwsz) == TKN_NUMBER) { GetToken(ppwsz); usTrigger = (USHORT) g_ulLastNumberToken; } else { fPrintAll = TRUE; } if (fPrintAll) { hr = DumpTriggers(fJob); } else { hr = DumpTrigger(fJob, usTrigger); } } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: PrintTriggerStrings // // Synopsis: Parse and execute the command to print one or all trigger // strings for a job. // // Arguments: [ppwsz] - command line // [fJob] - TRUE=>use g_pJob, FALSE=>use g_pJobQueue // // Returns: S_OK - string(s) printed // E_* - error logged // // Modifies: *[ppwsz] // // History: 01-05-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT PrintTriggerStrings(WCHAR **ppwsz, CHAR *szJobOrQueue, BOOL fJob) { HRESULT hr = S_OK; TOKEN tkn; BOOL fAllTriggers = TRUE; USHORT usTrigger; USHORT cTriggers; SHORT i; WCHAR * pwszTriggerString; do { tkn = PeekToken(ppwsz); if (tkn == TKN_NUMBER) { GetToken(ppwsz); fAllTriggers = FALSE; usTrigger = (USHORT) g_ulLastNumberToken; } 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; } if (!cTriggers) { g_Log.Write(LOG_TEXT, "There are no triggers on the %s", szJobOrQueue); break; } if (fAllTriggers) { g_Log.Write(LOG_TEXT, "All %u triggers on %s:", cTriggers, szJobOrQueue); g_Log.Write(LOG_TEXT, "Index Value"); g_Log.Write(LOG_TEXT, "----- -----------------------------------------------------"); for (i = 0; i < cTriggers; i++) { if (fJob) { hr = g_pJob->GetTriggerString(i, &pwszTriggerString); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetTriggerString"); } else { #ifdef NOT_YET hr = g_pJobQueue->GetTriggerString(i, &pwszTriggerString); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetTriggerString"); #endif // NOT_YET hr = E_NOTIMPL; } g_Log.Write(LOG_TEXT, "% 5d %S", i, pwszTriggerString); CoTaskMemFree(pwszTriggerString); if (i < cTriggers - 1) { g_Log.Write(LOG_TEXT, ""); } } } else { g_Log.Write(LOG_TEXT, "Trigger %u:", usTrigger); if (fJob) { hr = g_pJob->GetTriggerString(usTrigger, &pwszTriggerString); LOG_AND_BREAK_ON_FAIL(hr, "ITask::GetTriggerString"); } else { #ifdef NOT_YET hr = g_pJobQueue->GetTriggerString(usTrigger, &pwszTriggerString); LOG_AND_BREAK_ON_FAIL(hr, "ITaskQueue::GetTriggerString"); #endif // NOT_YET hr = E_NOTIMPL; } g_Log.Write(LOG_TEXT, "%S", pwszTriggerString); CoTaskMemFree(pwszTriggerString); } } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: Run // // Synopsis: Run job or queue object. // // Arguments: [fJob] - TRUE=>use g_pJob, FALSE=>use g_pJobQueue // // Returns: Result of ITask[Queue]::Run // // History: 01-11-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT Run(BOOL fJob) { HRESULT hr = S_OK; if (fJob) { g_Log.Write(LOG_TRACE, "Running job"); hr = g_pJob->Run(); if (FAILED(hr)) { g_Log.Write(LOG_FAIL, "ITask::Run hr=%#010x", hr); } } else { #ifdef NOT_YET g_Log.Write(LOG_TRACE, "Running queue"); hr = g_pJobQueue->Run(); if (FAILED(hr)) { g_Log.Write(LOG_FAIL, "ITaskQueue::Run hr=%#010x", hr); } #endif // NOT_YET hr = E_NOTIMPL; } return hr; } //+--------------------------------------------------------------------------- // // Function: Save // // Synopsis: Persist the global job or queue to the file specified in // the command line // // Arguments: [ppwsz] - command line. // [szJobOrQueue] - "Job" or "Queue" // [fJob] - TRUE=>use global job, FALSE=>use global queue // // Returns: S_OK - job or queue persisted // E_* - error logged // // History: 01-10-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT Save(WCHAR **ppwsz, CHAR *szJobOrQueue, BOOL fJob) { HRESULT hr = S_OK; TOKEN tkn; WCHAR *pwszFilename = NULL; SpIPersistFile spPersistFile; do { tkn = PeekToken(ppwsz); if (tkn == TKN_STRING) { hr = GetFilename(ppwsz, L"filename for save"); BREAK_ON_FAILURE(hr); pwszFilename = g_wszLastStringToken; g_Log.Write(LOG_TRACE, "Saving %s to %S", szJobOrQueue, g_wszLastStringToken); } else { g_Log.Write(LOG_TRACE, "Saving %s", szJobOrQueue); } if (fJob) { g_pJob->QueryInterface( IID_IPersistFile, (VOID**)(IPersistFile**)&spPersistFile); LOG_AND_BREAK_ON_FAIL(hr, "ITask::QI(IPersistFile)"); } else { g_pJobQueue->QueryInterface( IID_IPersistFile, (VOID**)(IPersistFile**)&spPersistFile); LOG_AND_BREAK_ON_FAIL(hr, "ITaskQueue::QI(IPersistFile)"); } DWORD ulTicks = GetTickCount(); hr = spPersistFile->Save(pwszFilename, TRUE); ulTicks = GetTickCount() - ulTicks; g_Log.Write(LOG_PERF, "Save took %lu ms", ulTicks); LOG_AND_BREAK_ON_FAIL(hr, "IPersistFile::Save"); } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: SchedActivate // // Synopsis: Perform activate job/queue command. // // Arguments: [ppwsz] - commandline. // // Returns: S_OK - activated job or queue // E_* - error logged // // History: 01-11-96 DavidMun Created // // Notes: This is the command-line front end to the utility routine // Activate. That routine is also called by other routines; // see SchedEnum. // //---------------------------------------------------------------------------- HRESULT SchedActivate(WCHAR **ppwsz) { HRESULT hr = S_OK; BOOL fJob; do { hr = Expect(TKN_STRING, ppwsz, L"job or queue filename"); BREAK_ON_FAILURE(hr); hr = Activate(g_wszLastStringToken, &g_pJob, &g_pJobQueue, &fJob); } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: SchedAddJob // // Synopsis: Perform add job command. // // Arguments: [ppwsz] - commandline. // // Returns: S_OK - added job // E_* - error logged // // History: 01-11-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT SchedAddJob(WCHAR **ppwsz) { HRESULT hr = S_OK; do { // // Note this filename may be a path relative to the job folder, so we // don't want to expand it to a full path name by calling GetFilename. // Just read it as a string instead. // hr = Expect(TKN_STRING, ppwsz, L"job filename"); BREAK_ON_FAILURE(hr); g_Log.Write(LOG_TRACE, "Adding job '%S'", g_wszLastStringToken); hr = g_pJobScheduler->AddWorkItem(g_wszLastStringToken, g_pJob); LOG_AND_BREAK_ON_FAIL(hr, "ITaskScheduler::AddWorkItemn"); } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: SchedCreateEnum // // Synopsis: Create a new jobs folder enumerator in the slot specified // by command line // // Arguments: [ppwsz] - command line // // Returns: S_OK - new enumerator created // E_INVALIDARG - command line has bad slot number // E_* - from ITaskScheduler::EnumJobs // // Modifies: g_apEnumJobs // // History: 01-30-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT SchedCreateEnum(WCHAR **ppwsz) { HRESULT hr = S_OK; ULONG idxSlot; do { hr = GetAndPrepareEnumeratorSlot(ppwsz, &idxSlot); BREAK_ON_FAILURE(hr); g_Log.Write(LOG_TRACE, "Creating new enumerator in slot %u", idxSlot); hr = g_pJobScheduler->Enum(&g_apEnumJobs[idxSlot]); LOG_AND_BREAK_ON_FAIL(hr, "ITaskScheduler::Enum"); } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: SchedDelete // // Synopsis: Perform delete job/queue command. // // Arguments: [ppwsz] - commandline. // // Returns: S_OK - deleted job or queue // E_* - error logged // // History: 01-11-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT SchedDelete(WCHAR **ppwsz) { HRESULT hr = S_OK; do { hr = Expect(TKN_STRING, ppwsz, L"job or queue filename to delete"); BREAK_ON_FAILURE(hr); g_Log.Write(LOG_TRACE, "Deleting '%S'", g_wszLastStringToken); hr = g_pJobScheduler->Delete(g_wszLastStringToken); LOG_AND_BREAK_ON_FAIL(hr, "ITaskScheduler::Delete"); } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: SchedEnum // // Synopsis: Perform enumerate jobs/queues command. // // Arguments: [ppwsz] - commandline. // // Returns: S_OK - job/queue names enumerated // E_* - error logged // // History: 01-12-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT SchedEnum(WCHAR **ppwsz) { HRESULT hr = S_OK; SpIEnumJobs spEnum; TOKEN tkn; ULONG i; ULONG cToFetch = DEFAULT_FETCH_COUNT; ULONG cFetched; BOOL fPrint = FALSE; do { g_Log.Write(LOG_TRACE, "Enumerating jobs and queues"); tkn = PeekToken(ppwsz); while (tkn == TKN_NUMBER || tkn == TKN_STRING) { GetToken(ppwsz); if (tkn == TKN_NUMBER) { cToFetch = g_ulLastNumberToken; } else { if (towupper(g_wszLastStringToken[0]) == L'P') { fPrint = TRUE; } } tkn = PeekToken(ppwsz); } hr = g_pJobScheduler->Enum(&spEnum); LOG_AND_BREAK_ON_FAIL(hr, "ITaskScheduler::Enum"); do { LPWSTR *ppwszFetched; LPWSTR *ppwszCur; hr = spEnum->Next(cToFetch, &ppwszFetched, &cFetched); LOG_AND_BREAK_ON_FAIL(hr, "IEnumJobs::Next"); for (i = 0, ppwszCur = ppwszFetched; i < cFetched; i++, ppwszCur++) { if (fPrint) { SpIJob spJob; SpIUnknown spQueue; BOOL fJob; hr = Activate(*ppwszCur, &spJob, &spQueue, &fJob); if (SUCCEEDED(hr)) { if (fJob) { DumpJob(spJob); DumpJobTriggers(spJob); } else { // BUGBUG call DumpQueue here g_Log.Write( LOG_WARN, "Ignoring %S: DumpQueue not implemented", *ppwszCur); } } g_Log.Write(LOG_TEXT, ""); g_Log.Write(LOG_TEXT, ""); } else { g_Log.Write(LOG_TEXT, " %S", *ppwszCur); } CoTaskMemFree(*ppwszCur); } CoTaskMemFree(ppwszFetched); } while (cFetched); } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: GetCredentials // // Synopsis: Retrieve the account name associated with the job's // credentials. // // Returns: Result of GetTargetComputer call. // // History: 06-04-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT GetCredentials(void) { HRESULT hr; LPWSTR pwszAccount; if (g_pJob == NULL) { g_Log.Write( LOG_FAIL, "A job object must be specified to get account information."); return(E_FAIL); } hr = g_pJob->GetAccountInformation(&pwszAccount); if (FAILED(hr)) { g_Log.Write(LOG_FAIL, "ITaskScheduler::GetAccountInformation hr=%#010x", hr); } else { g_Log.Write(LOG_TRACE, "Credential account name = '%S'", pwszAccount); CoTaskMemFree(pwszAccount); } return(hr); } //+--------------------------------------------------------------------------- // // Function: SchedGetMachine // // Synopsis: Perform Get Machine command (print target computer). // // Returns: Result of GetTargetComputer call. // // History: 06-04-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT SchedGetMachine() { HRESULT hr; LPWSTR pwszComputer; hr = g_pJobScheduler->GetTargetComputer(&pwszComputer); if (FAILED(hr)) { g_Log.Write(LOG_FAIL, "ITaskScheduler::GetTargetComputer hr=%#010x", hr); } else { g_Log.Write(LOG_TRACE, "TargetComputer = '%S'", pwszComputer); CoTaskMemFree(pwszComputer); } return hr; } //+--------------------------------------------------------------------------- // // Function: SchedIsJobOrQueue // // Synopsis: Call the ITaskScheduler::IsJob and IsQueue commands on the // specified filename and report the results. // // Arguments: [ppwsz] - commandline. // // Returns: S_OK - methods called // E_* - invalid commandline // // History: 03-11-96 DavidMun Created // // Notes: Don't consider errors returned by the IsJob and IsQueue // methods as errors in calling this routine. That would // halt a script that purposely gives them bad paths. // //---------------------------------------------------------------------------- HRESULT SchedIsJobOrQueue(WCHAR **ppwsz) { HRESULT hr = S_OK; do { hr = Expect(TKN_STRING, ppwsz, L"filename to test"); BREAK_ON_FAILURE(hr); hr = g_pJobScheduler->IsOfType(g_wszLastStringToken, IID_ITask); g_Log.Write( LOG_TRACE, "ITaskScheduler::IsOfType(%S) returned %#010x", g_wszLastStringToken, hr); #ifdef NOT_YET hr = g_pJobScheduler->IsQueue(g_wszLastStringToken); g_Log.Write( LOG_TRACE, "ITaskScheduler::IsQueue(%S) returned %#010x", g_wszLastStringToken, hr); #endif hr = S_OK; } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: SchedNewJob // // Synopsis: Perform new job command. // // Arguments: [ppwsz] - commandline. // // Returns: S_OK - created new job // E_* - error logged // // History: 01-11-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT SchedNewJob(WCHAR **ppwsz) { HRESULT hr = S_OK; SpIJob spNewJob; do { hr = Expect(TKN_STRING, ppwsz, L"job filename"); BREAK_ON_FAILURE(hr); g_Log.Write(LOG_TRACE, "Creating new job '%S'", g_wszLastStringToken); DWORD ulTicks = GetTickCount(); hr = g_pJobScheduler->NewWorkItem( g_wszLastStringToken, CLSID_CTask, IID_ITask, (IUnknown**)(ITask**)&spNewJob); ulTicks = GetTickCount() - ulTicks; g_Log.Write(LOG_PERF, "NewWorkItem call took %lu ms", ulTicks); LOG_AND_BREAK_ON_FAIL(hr, "ITaskScheduler::NewWorkItem"); // // Replace the global job object with the new one. // g_pJob->Release(); spNewJob.Transfer(&g_pJob); } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: SetCredentials // // Synopsis: Call SetAccountInformation to set the job credentials. // // Arguments: [ppwsz] - command line. // // Returns: Result of calling ITaskScheduler::SetAccountInformation // // History: 06-22-96 MarkBl Created // 07-22-96 DavidMun Method now takes just two arguments // //---------------------------------------------------------------------------- HRESULT SetCredentials(WCHAR **ppwsz) { WCHAR wszAccountNew[MAX_USERNAME + 1]; //see sched\inc\defines.hxx WCHAR wszPasswordNew[MAX_PASSWORD + 1]; HRESULT hr; TOKEN tkn; ZeroMemory(wszAccountNew, sizeof(wszAccountNew)); ZeroMemory(wszPasswordNew, sizeof(wszPasswordNew)); do { hr = Expect(TKN_STRING, ppwsz, L"new account name"); BREAK_ON_FAILURE(hr); wcsncpy(wszAccountNew, g_wszLastStringToken, min(wcslen(g_wszLastStringToken) + 1, MAX_USERNAME)); wszAccountNew[MAX_USERNAME] = L'\0'; hr = Expect(TKN_STRING, ppwsz, L"new account password"); BREAK_ON_FAILURE(hr); wcsncpy(wszPasswordNew, g_wszLastStringToken, min(wcslen(g_wszLastStringToken) + 1, MAX_PASSWORD)); wszPasswordNew[MAX_PASSWORD] = L'\0'; g_Log.Write(LOG_TRACE, "Setting account information"); hr = g_pJob->SetAccountInformation(wszAccountNew, wcscmp(wszPasswordNew, L"NULL") ? wszPasswordNew : NULL); if (FAILED(hr)) { g_Log.Write( LOG_FAIL, "ITaskScheduler::SetAccountInformation hr=%#010x", hr); } } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: SchedSetMachine // // Synopsis: Call SetTargetComputer with computer name (NULL if not // specified on command line). // // Arguments: [ppwsz] - command line. // // Returns: Result of calling ITaskScheduler::SetTargetComputer // // History: 06-04-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT SchedSetMachine(WCHAR **ppwsz) { HRESULT hr; TOKEN tkn; LPWSTR pwszComputer = NULL; tkn = PeekToken(ppwsz); if (tkn == TKN_STRING) { GetToken(ppwsz); pwszComputer = g_wszLastStringToken; } g_Log.Write(LOG_TRACE, "Setting target computer to '%S'", pwszComputer); hr = g_pJobScheduler->SetTargetComputer(pwszComputer); if (FAILED(hr)) { g_Log.Write( LOG_FAIL, "ITaskScheduler::SetTargetComputer hr=%#010x", hr); } return hr; } //+--------------------------------------------------------------------------- // // Function: SetJob // // Synopsis: Set one or more properties on the global job. // // Arguments: [ppwsz] - command line. // // Returns: S_OK - job properties set // E_* - error logged // // History: 01-10-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT SetJob(WCHAR **ppwsz) { HRESULT hr = S_OK; CJobProp JobProperties; do { g_Log.Write(LOG_TRACE, "Setting job's properties"); hr = JobProperties.Parse(ppwsz); BREAK_ON_FAILURE(hr); // // Set the job's properties to the values we just parsed // hr = JobProperties.SetActual(g_pJob); } while (0); return hr; } //+--------------------------------------------------------------------------- // // Function: SetTrigger // // Synopsis: Parse and execute the set trigger command. // // Arguments: [ppwsz] - command line // // Returns: S_OK - trigger modified // E_* - error logged // // Modifies: *[ppwsz] // // History: 01-05-96 DavidMun Created // //---------------------------------------------------------------------------- HRESULT SetTrigger(WCHAR **ppwsz, BOOL fJob) { HRESULT hr = S_OK; CTrigProp TriggerProps; SHORT usTrigger = 0; SpIJobTrigger spTrigger; do { if (PeekToken(ppwsz) == TKN_NUMBER) { GetToken(ppwsz); usTrigger = (SHORT) g_ulLastNumberToken; } g_Log.Write( LOG_TRACE, "Setting properties on trigger %u", usTrigger); hr = TriggerProps.Parse(ppwsz); BREAK_ON_FAILURE(hr); 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 = TriggerProps.SetActual(spTrigger); } while (0); return hr; }