|
|
// File: schedule.cpp
//
// Contents: Functions needed to start, query, add, remove tasks
// in Task Scheduler
//
// Microsoft Desktop Themes for Windows
// Copyright (c) 1998-1999 Microsoft Corporation. All rights reserved.
#include <wchar.h>
#include <windows.h>
#include <mbctype.h>
#include <objbase.h>
#include <initguid.h>
#include <mstask.h>
#include <msterr.h>
#include "frost.h"
#define MSG_BOX_TSERR(hw,msg) MessageBox(hw, msg, szThemeName,\
MB_OK | MB_ICONERROR | MB_APPLMODAL)
#define SCHED_CLASS TEXT("SAGEWINDOWCLASS")
#define SCHED_TITLE TEXT("SYSTEM AGENT COM WINDOW")
#define SCHED_SERVICE_APP_NAME TEXT("mstask.exe")
#define SCHED_SERVICE_NAME TEXT("Schedule")
#define EVERY_MONTH (TASK_JANUARY | TASK_FEBRUARY | TASK_MARCH | TASK_APRIL |\
TASK_MAY | TASK_JUNE | TASK_JULY | TASK_AUGUST |\ TASK_SEPTEMBER | TASK_OCTOBER | TASK_NOVEMBER |\ TASK_DECEMBER)
//+--------------------------------------------------------------------------
// Global variables defined in GLOBAL.H for compat. with C sources
//---------------------------------------------------------------------------
extern "C" HWND hWndApp = NULL; extern "C" HINSTANCE hInstApp = NULL;
//+--------------------------------------------------------------------------
// Global variables for use in SCHEDULE.CPP only
//---------------------------------------------------------------------------
ITaskScheduler *g_pITaskScheduler = NULL; TCHAR szRunServices[] = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunServices"); TCHAR szScheduler[] = TEXT("SchedulingAgent"); TCHAR szMSTask[] = TEXT("mstask.exe"); TCHAR szUserName[MAX_PATH]; TCHAR szPassword[MAX_PATH];
//+--------------------------------------------------------------------------
// Function Prototypes
//---------------------------------------------------------------------------
HRESULT Init(void); void Cleanup(void); extern "C" BOOL IsTaskSchedulerRunning(); extern "C" BOOL StartTaskScheduler(BOOL); extern "C" BOOL IsThemesScheduled(); extern "C" BOOL AddThemesTask(LPTSTR, BOOL); extern "C" BOOL DeleteThemesTask(); extern "C" BOOL HandDeleteThemesTask(); extern "C" BOOL IsPlatformNT(); extern "C" BOOL GetCurrentUser(LPTSTR, DWORD, LPTSTR, DWORD, LPTSTR, DWORD); extern "C" BOOL GetTextualSid(PSID, LPTSTR, LPDWORD); extern "C" VOID BuildNTJobName(LPTSTR); extern "C" BOOL IsUserAdmin();
//+--------------------------------------------------------------------------
//
// Function: PasswordDlgProc()
//
// Synopsis: WINNT only -- prompts user for name and password.
//
// Arguments: none (void)
//
//---------------------------------------------------------------------------
INT_PTR CALLBACK PasswordDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { TCHAR szPWConfirm[MAX_PATH]; TCHAR szErrMsg[MAX_PATH]; TCHAR szThemeName[MAX_STRLEN]; // Used for msgbox title
DWORD dwSize = 0; TCHAR szProfile[MAX_PATH];
switch(uMsg)
{
case WM_INITDIALOG:
if (GetCurrentUser(szPassword, /* Actually user name */ ARRAYSIZE(szPassword), szUserName, /* Actually domain name */ ARRAYSIZE(szUserName), szProfile, ARRAYSIZE(szProfile))) { // GetCurrentUser succeeded so build the domain\user
//
// Remember these variable names are bogus --
// szUserName is actually the domain name
// szPassword is actually the user name
//
if (szPassword[0]) lstrcat(szUserName, TEXT("\\")); lstrcat(szUserName, szPassword); } else { // GetCurrentUser failed so do this as last resort
dwSize = ARRAYSIZE(szUserName); GetUserName(szUserName, &dwSize); } *szPassword = 0;
SetDlgItemText(hDlg, EDIT_USER, szUserName); SetFocus(GetDlgItem(hDlg, EDIT_PW));
return FALSE; // Return false to keep focus on PW control
break;
case WM_COMMAND:
switch (wParam)
{
case IDOK: GetDlgItemText(hDlg, EDIT_USER, szUserName, MAX_PATH); GetDlgItemText(hDlg, EDIT_PW, szPassword, MAX_PATH); GetDlgItemText(hDlg, EDIT_PWCONFIRM, szPWConfirm, MAX_PATH);
if (lstrcmp(szPassword, szPWConfirm)) { // PW and PWCONFIRM don't match
LoadString(hInstApp, STR_APPNAME, szThemeName, MAX_STRLEN); LoadString(hInstApp, STR_PW_NOMATCH, szErrMsg, MAX_PATH); MessageBox(hWndApp, szErrMsg, szThemeName, MB_OK | MB_ICONERROR | MB_APPLMODAL); SetDlgItemText(hDlg, EDIT_PW, TEXT("\0")); SetDlgItemText(hDlg, EDIT_PWCONFIRM, TEXT("\0")); SetActiveWindow(GetDlgItem(hDlg, EDIT_PW)); SetFocus(GetDlgItem(hDlg, EDIT_PW)); break; }
else
{ EndDialog(hDlg,1); break; }
case IDCANCEL: szUserName[0] = TEXT('\0'); szPassword[0] = TEXT('\0'); EndDialog(hDlg, 0); break; }
break;
default: return FALSE;
} // switch uMsg
return TRUE;
} // PasswordDlgProc
//+--------------------------------------------------------------------------
//
// Function: IsPlatformNT()
//
// Synopsis: Checks to see if the os is NT or not.
//
// Arguments: none (void)
//
// Returns: TRUE if NT, FALSE if not.
//
//---------------------------------------------------------------------------
extern "C" BOOL IsPlatformNT() { OSVERSIONINFO osver;
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
// Determine what version of OS we are running on.
GetVersionEx(&osver);
if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) return TRUE; else return FALSE; }
//+--------------------------------------------------------------------------
//
// Function: IsTaskSchedulerRunning()
//
// Synopsis: Looks for TS window to determince TS is running.
//
// Arguments: none (void)
//
// Returns: TRUE if running, FALSE if not.
//
//---------------------------------------------------------------------------
extern "C" BOOL IsTaskSchedulerRunning() { HWND hwnd = FindWindow(SCHED_CLASS, SCHED_TITLE);
if (hwnd == NULL) { //MessageBox(hWndApp, TEXT("TS is not running"), TEXT("Desktop Themes"), MB_OK | MB_APPLMODAL);
return FALSE; } else { //MessageBox(hWndApp, TEXT("TS is running"), TEXT("Desktop Themes"), MB_OK | MB_APPLMODAL);
return TRUE; } }
//---------------------------------------------------------------------------
// Function: StartTaskScheduler
// Synopsis: Start the task scheduler service if it isn't already running.
// Arguments: bPrompt -- TRUE == prompt user before starting.
// FALSE == just start it, don't prompt user.
// Returns: TRUE if successful, FALSE if not.
// Notes: This function works in Win9x only.
// If the service is running but paused, does nothing.
//---------------------------------------------------------------------------
extern "C" BOOL StartTaskScheduler(BOOL bPrompt) { STARTUPINFO sui; PROCESS_INFORMATION pi; TCHAR szApp[MAX_PATH]; LPTSTR pszPath; DWORD dwRet; BOOL fRet; TCHAR szErrMsg[MAX_PATH]; TCHAR szThemeName[MAX_STRLEN]; // Used for msgbox title
int MBChoice; // User's reply to Yes/No dialog
DWORD dwDisposition; HKEY hKey; LONG lret;
LoadString(hInstApp, STR_APPNAME, szThemeName, MAX_STRLEN);
HWND hwnd = FindWindow(SCHED_CLASS, SCHED_TITLE); if (hwnd != NULL) { // It is already running.
return TRUE; }
// If specified, prompt user before attempting to start
// Task Scheduler.
if (bPrompt) { LoadString(hInstApp, STR_ERRTSNOTRUN, szErrMsg, MAX_PATH); MBChoice = MessageBox(hWndApp, szErrMsg, szThemeName, MB_YESNO | MB_ICONQUESTION | MB_APPLMODAL);
// Did user opt to NOT start task scheduler?
if (IDYES != MBChoice) return FALSE; }
if (!IsPlatformNT()) {
// Start the Win9x version of TaskScheduler.
// Execute the task scheduler process.
ZeroMemory(&sui, sizeof(sui)); sui.cb = sizeof(STARTUPINFO);
dwRet = SearchPath(NULL, SCHED_SERVICE_APP_NAME, NULL, MAX_PATH, szApp, &pszPath);
if (dwRet == 0) { LoadString(hInstApp, STR_ERRTSNOTFOUND, szErrMsg, MAX_PATH); MessageBox(hWndApp, szErrMsg, szThemeName, MB_OK | MB_ICONERROR | MB_APPLMODAL); return FALSE; }
fRet = CreateProcess(szApp, NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, NULL, NULL, &sui, &pi);
if (fRet == 0) { LoadString(hInstApp, STR_ERRTSNOSTART, szErrMsg, MAX_PATH); MessageBox(hWndApp, szErrMsg, szThemeName, MB_OK | MB_ICONERROR | MB_APPLMODAL); return FALSE; }
CloseHandle(pi.hProcess); CloseHandle(pi.hThread);
// Assume that MSTASK.EXE was successfully started. We need to
// add mstask.exe to the RunServices branch of the registry.
hKey = NULL; lret = RegCreateKeyEx(HKEY_LOCAL_MACHINE, szRunServices, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisposition);
if (lret == ERROR_SUCCESS) { // RegDeleteValue(hKey, szScheduler);
lret = RegSetValueEx(hKey, szScheduler, 0, REG_SZ, (CONST BYTE *)szMSTask, SZSIZEINBYTES(szMSTask)); }
if (hKey) RegCloseKey(hKey);
return TRUE; } else {
// If not Win9x then start the NT version as a TaskScheduler service.
SC_HANDLE hSC = NULL; SC_HANDLE hSchSvc = NULL;
// Does the user have administrative privileges? If not, the
// user can't start TS.
if (!IsUserAdmin()) { LoadString(hInstApp, STR_ERRTSNOTADMIN, szErrMsg, MAX_PATH); MessageBox(hWndApp, szErrMsg, szThemeName, MB_OK | MB_ICONERROR | MB_APPLMODAL); return FALSE; }
hSC = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (hSC == NULL) {
return FALSE; // NEED TO ADD ERROR DIALOG HERE
// return GetLastError();
}
hSchSvc = OpenService(hSC, SCHED_SERVICE_NAME, SERVICE_START | SERVICE_QUERY_STATUS);
CloseServiceHandle(hSC);
if (hSchSvc == NULL) { LoadString(hInstApp, STR_ERRTSNOSTART, szErrMsg, MAX_PATH); MessageBox(hWndApp, szErrMsg, szThemeName, MB_OK | MB_ICONERROR | MB_APPLMODAL); return FALSE; }
SERVICE_STATUS SvcStatus;
if (QueryServiceStatus(hSchSvc, &SvcStatus) == FALSE) { CloseServiceHandle(hSchSvc); LoadString(hInstApp, STR_ERRTSNOSTART, szErrMsg, MAX_PATH); MessageBox(hWndApp, szErrMsg, szThemeName, MB_OK | MB_ICONERROR | MB_APPLMODAL); return FALSE; }
if (SvcStatus.dwCurrentState == SERVICE_RUNNING) { // The service is already running.
CloseServiceHandle(hSchSvc); return TRUE; }
if (StartService(hSchSvc, 0, NULL) == FALSE) { CloseServiceHandle(hSchSvc); LoadString(hInstApp, STR_ERRTSNOSTART, szErrMsg, MAX_PATH); MessageBox(hWndApp, szErrMsg, szThemeName, MB_OK | MB_ICONERROR | MB_APPLMODAL); return FALSE; }
CloseServiceHandle(hSchSvc);
return TRUE; }
} // END StartTaskScheduler()
//+--------------------------------------------------------------------------
//
// Function: Init()
//
// Synopsis: Called to initialize and instantiate a task
// scheduler object.
//
// Arguments: none (void)
//
// Returns: HRESULT indicating success or failure. S_OK on success.
//
// Side effect: Sets global pointer g_pITaskScheduler, for use in other
// functions.
//
//---------------------------------------------------------------------------
HRESULT Init() { HRESULT hr = S_OK;
// Bring in the library
hr = CoInitialize(NULL); if (FAILED(hr)) { return hr; }
// Create the pointer to Task Scheduler object
// CLSID from the header file mstask.h
hr = CoCreateInstance( CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (void **) &g_pITaskScheduler);
// Should we fail, unload the library
if (FAILED(hr)) { CoUninitialize(); }
return hr; }
//+--------------------------------------------------------------------------
//
// Function: Cleanup()
//
// Synopsis: Called to clean up OLE, memory, etc. before termination
//
// Arguments: none (void)
//
// Returns: nothing (void)
//
// Side effect: Cancels the global pointer g_pITaskScheduler.
//
//---------------------------------------------------------------------------
void Cleanup() { if (g_pITaskScheduler) { g_pITaskScheduler->Release(); g_pITaskScheduler = NULL; }
// Unload the library, now that our pointer is freed.
CoUninitialize(); return; }
//+--------------------------------------------------------------------------
//
// Function: IsThemesScheduled()
//
// Synopsis: Enumerates tasks and returns TRUE if Themes.job exists.
// Returns FALSE if it does not.
//
// Arguments: none (void). Requires g_pITaskScheduler.
//
// Returns: TRUE if Themes.job exists, else FALSE
//
//---------------------------------------------------------------------------
extern "C" BOOL IsThemesScheduled() { HRESULT hr = S_OK, hrLoop = S_OK; IEnumWorkItems *pIEnumWorkItems; IUnknown *pIU; ITask *pITask; ULONG ulTasksToGet = 1, ulActualTasksRetrieved = 0; LPWSTR *rgpwszNames; TCHAR szDefaultJobName[MAX_PATH]; BOOL bResult; UINT uCodePage; #ifndef UNICODE
CHAR szJobNameA[MAX_PATH]; #endif
// For protection
g_pITaskScheduler = NULL;
// String conversion initialization
uCodePage = _getmbcp();
// Attempt to initialize OLE and fill in the global g_pITaskScheduler
hr = Init(); if (FAILED(hr)) { return FALSE; }
// Get the default name for a Themes task
LoadString(hInstApp, STR_JOB_NAME, szDefaultJobName, MAX_PATH);
// If this is NT we need to append the user profile name onto the
// end of this task.
if (IsPlatformNT()) BuildNTJobName(szDefaultJobName);
//
// Get an enumeration pointer, using ITaskScheduler::Enum
//
hr = g_pITaskScheduler->Enum(&pIEnumWorkItems); if (FAILED(hr)) { // LoadString(hInstApp, STR_ERRTS, szErrMsg, MAX_PATH);
// MSG_BOX_TSERR(hWndApp, szErrMsg);
Cleanup(); return FALSE; }
bResult = FALSE; do { // Get a single work item, using IEnumWorkItems::Next
hrLoop = pIEnumWorkItems->Next(ulTasksToGet, &rgpwszNames, &ulActualTasksRetrieved); if (hrLoop == S_FALSE) { // There are no more waiting tasks to look at
break; }
// Attach to the work item, using ITaskScheduler::Activate
hr = g_pITaskScheduler->Activate(rgpwszNames[0], IID_ITask, &pIU); if (FAILED(hr)) { // LoadString(hInstApp, STR_ERRTS, szErrMsg, MAX_PATH);
// MSG_BOX_TSERR(hWndApp, szErrMsg);
bResult = FALSE; break; }
// QI pIU for pITask
hr = pIU->QueryInterface(IID_ITask, (void **) &pITask); pIU->Release(); pIU = NULL; if (FAILED(hr)) { // LoadString(hInstApp, STR_ERRTS, szErrMsg, MAX_PATH);
// MSG_BOX_TSERR(hWndApp, szErrMsg);
bResult = FALSE; break; }
// Compare task name
#ifndef UNICODE
// No UNICODE so we need to convert the wide string returned
// by ITask into an ANSI string.
WideCharToMultiByte(uCodePage, 0, rgpwszNames[0], -1, szJobNameA, MAX_PATH, NULL, NULL); // MessageBox(hWndApp, szJobNameA, szThemeName,
// MB_OK | MB_APPLMODAL);
if (!lstrcmp(szJobNameA, szDefaultJobName)) bResult = TRUE; #else
// We're living in a UNICODE world so no need to convert
// the string from ITask.
// MessageBox(hWndApp, rgpwszNames[0], szThemeName,
// MB_OK | MB_APPLMODAL);
if (!lstrcmp(rgpwszNames[0], szDefaultJobName)) bResult = TRUE; #endif
// Clean up each element in the array of job names, then
// clean up the final array.
CoTaskMemFree(rgpwszNames[0]); CoTaskMemFree(rgpwszNames);
// Free the ITask pointer
pITask->Release();
} while(!bResult);
// Release the enumeration pointer
pITask = NULL;
pIEnumWorkItems->Release(); pIEnumWorkItems = NULL;
Cleanup(); return bResult; //
}
//+--------------------------------------------------------------------------
//
// Function: DeleteThemesTask()
//
// Synopsis: Deletes Themes task from Task Scheduler.
//
// Returns: TRUE if OK, FALSE if FAIL.
//
//---------------------------------------------------------------------------
extern "C" BOOL DeleteThemesTask() { HRESULT hr = S_OK; UINT uCodePage; TCHAR szDefaultJobName[MAX_PATH]; #ifndef UNICODE
WCHAR szJobNameW[MAX_PATH]; #endif
// String conversion initialization
uCodePage = _getmbcp();
// For protection
g_pITaskScheduler = NULL;
// Attempt to initialize OLE and fill in the global g_pITaskScheduler
hr = Init(); if (FAILED(hr)) { // LoadString(hInstApp, STR_ERRTS, szErrMsg, MAX_PATH);
// MSG_BOX_TSERR(hWndApp, szErrMsg);
return FALSE; }
// Get the default name for a Themes task
LoadString(hInstApp, STR_JOB_NAME, szDefaultJobName, MAX_PATH);
// If this is NT we need to append the user profile name onto the
// end of this task.
if (IsPlatformNT()) BuildNTJobName(szDefaultJobName);
#ifndef UNICODE
// No UNICODE so convert the string to WCHAR format to
// please the TS interface
MultiByteToWideChar(uCodePage, 0, szDefaultJobName, -1, szJobNameW, MAX_PATH);
// Delete it
hr = g_pITaskScheduler->Delete(szJobNameW); #else // UNICODE
// We're UNICODE so we don't need to convert the string before
// calling TS
hr = g_pITaskScheduler->Delete(szDefaultJobName); #endif
Cleanup();
return TRUE; // Returns TRUE regardless of hr value.
}
//+--------------------------------------------------------------------------
//
// Function: AddThemesTask()
//
// Synopsis: Adds a new work item to the Scheduled Tasks folder.
//
// Arguments: lpwszThemesExe - fully qualified path to Themes.exe.
// bShowErrors - if TRUE, ATT shows error dialogs else
// it fails silently.
//
// Returns: TRUE if successful, FALSE if not.
//
//---------------------------------------------------------------------------
extern "C" BOOL AddThemesTask(LPTSTR lpszThemesExe, BOOL bShowErrors)
{ HRESULT hr = S_OK; IUnknown *pIU; IPersistFile *pIPF; ITask *pITask; ITaskTrigger *pITaskTrig; DWORD dwTaskFlags, dwTrigFlags; WORD wTrigNumber; TASK_TRIGGER TaskTrig; UINT uCodePage;
//TCHAR szUserName[MAX_PATH];
//TCHAR szPassword[MAX_PATH];
WCHAR szRotateCommandW[] = L"/r"; TCHAR szDefaultJobName[MAX_PATH]; TCHAR szJobComment[MAX_PATH]; #ifndef UNICODE
WCHAR szUserNameW[MAX_PATH]; WCHAR szPasswordW[MAX_PATH]; WCHAR szThemesExeW[MAX_PATH]; WCHAR szJobNameW[MAX_PATH]; WCHAR szJobCommentW[MAX_PATH]; #endif
SYSTEMTIME LocalTime; TCHAR szErrMsg[MAX_PATH]; TCHAR szThemeName[MAX_STRLEN]; // msg box title
HKEY hKey; DWORD dwDisposition; LONG lret; INT_PTR iResult;
LoadString(hInstApp, STR_APPNAME, szThemeName, MAX_STRLEN); LoadString(hInstApp, STR_JOB_NAME, szDefaultJobName, MAX_PATH); LoadString(hInstApp, STR_JOB_COMMENT, szJobComment, MAX_PATH);
// If this is NT we need to append the user profile name onto the
// end of this task.
if (IsPlatformNT()) BuildNTJobName(szDefaultJobName);
// String conversion initialization
uCodePage = _getmbcp();
// For protection
g_pITaskScheduler = NULL;
// Attempt to initialize OLE and fill in the global g_pITaskScheduler
hr = Init(); if (FAILED(hr)) { if (bShowErrors) { LoadString(hInstApp, STR_ERRTS, szErrMsg, MAX_PATH); MSG_BOX_TSERR(hWndApp, szErrMsg); } return FALSE; }
// Add the task. Most likely failure is that work item already exists.
// Uses ITaskScheduler::NewWorkItem
#ifndef UNICODE
// No UNICODE so convert string to wide before adding task
MultiByteToWideChar(uCodePage, 0, szDefaultJobName, -1, szJobNameW, MAX_PATH);
hr = g_pITaskScheduler->NewWorkItem(szJobNameW, CLSID_CTask, IID_ITask, &pIU); #else
// UNICODE, so no need to convert string to WIDE before adding task
hr = g_pITaskScheduler->NewWorkItem(szDefaultJobName, CLSID_CTask, IID_ITask, &pIU); #endif
if (FAILED(hr)) { if (bShowErrors) { LoadString(hInstApp, STR_ERRTS, szErrMsg, MAX_PATH); MSG_BOX_TSERR(hWndApp, szErrMsg); } Cleanup(); return FALSE; }
// We now have an IUnknown pointer. This is queried for an ITask
// pointer on the work item we just added.
hr = pIU->QueryInterface(IID_ITask, (void **) &pITask); if (FAILED(hr)) { if (bShowErrors) { LoadString(hInstApp, STR_ERRTS, szErrMsg, MAX_PATH); MSG_BOX_TSERR(hWndApp, szErrMsg); } pIU->Release(); Cleanup(); return FALSE; }
// Cleanup pIUnknown, as we are done with it.
pIU->Release(); pIU = NULL;
//
// If this is for NT we need to get and set the user account
// information. ITask::SetAccountInformation
//
if (IsPlatformNT()) {
szUserName[0] = TEXT('\0'); // global user name string
szPassword[0] = TEXT('\0'); // global password string
// Prompt for the user name and password
//
// Password dialog returns:
// -1 if DialogBox() fails
// 0 if user cancels
// 1 if PW entered OK
iResult = 0; iResult = DialogBox(hInstApp, MAKEINTRESOURCE(DLG_PASSWORD), hWndApp, PasswordDlgProc);
if (iResult < 1) { // Either the password dialog failed or the user Canceled
// it so bail out.
pITask->Release(); Cleanup(); return FALSE; }
#ifndef UNICODE
// No UNICODE so we need to convert from ANSI to WCHAR before
// calling SetAccountInformation
MultiByteToWideChar(uCodePage, 0, szUserName, -1, szUserNameW, MAX_PATH);
MultiByteToWideChar(uCodePage, 0, szPassword, -1, szPasswordW, MAX_PATH);
hr = pITask->SetAccountInformation(szUserNameW, szPasswordW);
#else
// UNICODE so no need to convert strings
hr = pITask->SetAccountInformation(szUserName, szPassword);
#endif // UNICODE
if (FAILED(hr)) { if (bShowErrors) { LoadString(hInstApp, STR_ERRTS, szErrMsg, MAX_PATH); MSG_BOX_TSERR(hWndApp, szErrMsg); } pITask->Release(); Cleanup(); return FALSE; }
} // IsPlatformNT
// Set command name with ITask::SetApplicationName
#ifndef UNICODE
// No UNICODE so need to convert string to WIDE
MultiByteToWideChar(uCodePage, 0, lpszThemesExe, -1, szThemesExeW, MAX_PATH);
hr = pITask->SetApplicationName(szThemesExeW); #else
// UNICODE so no need to convert string
hr = pITask->SetApplicationName(lpszThemesExe); #endif
if (FAILED(hr)) { if (bShowErrors) { LoadString(hInstApp, STR_ERRTS, szErrMsg, MAX_PATH); MSG_BOX_TSERR(hWndApp, szErrMsg); } pITask->Release(); Cleanup(); return FALSE; }
// Set task parameters with ITask::SetParameters
hr = pITask->SetParameters(szRotateCommandW); if (FAILED(hr)) { if (bShowErrors) { LoadString(hInstApp, STR_ERRTS, szErrMsg, MAX_PATH); MSG_BOX_TSERR(hWndApp, szErrMsg); } pITask->Release(); Cleanup(); return FALSE; }
// Set the comment, so we know how this job got there
// Uses ITask::SetComment
#ifndef UNICODE
// No UNICODE so convert to WIDE
MultiByteToWideChar(uCodePage, 0, szJobComment, -1, szJobCommentW, MAX_PATH);
hr = pITask->SetComment(szJobCommentW); #else
// UNICODE so no need to convert string
hr = pITask->SetComment(szJobComment); #endif
if (FAILED(hr)) { if (bShowErrors) { LoadString(hInstApp, STR_ERRTS, szErrMsg, MAX_PATH); MSG_BOX_TSERR(hWndApp, szErrMsg); } pITask->Release(); Cleanup(); return FALSE; }
// Set the flags on the task object
// Use ITask::SetFlags
dwTaskFlags = NULL; hr = pITask->SetFlags(dwTaskFlags); if (FAILED(hr)) { if (bShowErrors) { LoadString(hInstApp, STR_ERRTS, szErrMsg, MAX_PATH); MSG_BOX_TSERR(hWndApp, szErrMsg); } pITask->Release(); Cleanup(); return FALSE; }
// Now, create a trigger to run the task at our specified time.
// Uses ITask::CreateTrigger()
hr = pITask->CreateTrigger(&wTrigNumber, &pITaskTrig); if (FAILED(hr)) { if (bShowErrors) { LoadString(hInstApp, STR_ERRTS, szErrMsg, MAX_PATH); MSG_BOX_TSERR(hWndApp, szErrMsg); } pITask->Release(); Cleanup(); return FALSE; }
// Now, fill in the trigger as necessary.
GetLocalTime(&LocalTime);
if (12 == LocalTime.wMonth) { LocalTime.wMonth = 1; LocalTime.wYear++; } else LocalTime.wMonth++;
dwTrigFlags = 0;
TaskTrig.cbTriggerSize = sizeof(TASK_TRIGGER); TaskTrig.Reserved1 = 0; TaskTrig.wBeginYear = LocalTime.wYear; TaskTrig.wBeginMonth = LocalTime.wMonth; TaskTrig.wBeginDay = 1; TaskTrig.wEndYear = 0; TaskTrig.wEndMonth = 0; TaskTrig.wEndDay = 0; TaskTrig.wStartHour = 14; TaskTrig.wStartMinute = 0; TaskTrig.MinutesDuration = 0; TaskTrig.MinutesInterval = 0; TaskTrig.rgFlags = dwTrigFlags; TaskTrig.TriggerType = TASK_TIME_TRIGGER_MONTHLYDATE; TaskTrig.Type.MonthlyDate.rgfDays = 1; TaskTrig.Type.MonthlyDate.rgfMonths = EVERY_MONTH; TaskTrig.wRandomMinutesInterval = 0; TaskTrig.Reserved2 = 0;
// Add this trigger to the task using ITaskTrigger::SetTrigger
hr = pITaskTrig->SetTrigger(&TaskTrig); if (FAILED(hr)) { if (bShowErrors) { LoadString(hInstApp, STR_ERRTS, szErrMsg, MAX_PATH); MSG_BOX_TSERR(hWndApp, szErrMsg); } pITaskTrig->Release(); pITask->Release(); Cleanup(); return FALSE; }
// Make the changes permanent
// Requires using IPersistFile::Save()
hr = pITask->QueryInterface(IID_IPersistFile, (void **) &pIPF); if (FAILED(hr)) { if (bShowErrors) { LoadString(hInstApp, STR_ERRTS, szErrMsg, MAX_PATH); MSG_BOX_TSERR(hWndApp, szErrMsg); } pITaskTrig->Release(); pITask->Release(); Cleanup(); return FALSE; }
hr = pIPF->Save(NULL, FALSE); if (FAILED(hr)) { if (bShowErrors) { LoadString(hInstApp, STR_ERRTS, szErrMsg, MAX_PATH); MSG_BOX_TSERR(hWndApp, szErrMsg); } pITaskTrig->Release(); pITask->Release(); pIPF->Release(); Cleanup(); return FALSE; }
// We no longer need ITask
pITask->Release(); pITask = NULL;
// Done with ITaskTrigger pointer
pITaskTrig->Release(); pITaskTrig = NULL;
// Done with IPersistFile
pIPF->Release(); pIPF = NULL; Cleanup();
// Finally -- we have successfully added the task but we need to
// make sure that Task Scheduler is in the RunServices branch of
// the registry so it will start every time.
hKey = NULL; lret = RegCreateKeyEx(HKEY_LOCAL_MACHINE, szRunServices, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisposition);
if (lret == ERROR_SUCCESS) { // RegDeleteValue(hKey, szScheduler);
lret = RegSetValueEx(hKey, szScheduler, 0, REG_SZ, (CONST BYTE *)szMSTask, (SZSIZEINBYTES(szMSTask) + 1)); }
if (hKey) RegCloseKey(hKey);
return TRUE; }
extern "C" BOOL HandDeleteThemesTask() { TCHAR szJobFile[MAX_PATH]; // Full path to %windir%\Tasks\Themes.job
TCHAR szDefaultJobName[MAX_PATH];
if (!GetWindowsDirectory(szJobFile, MAX_PATH)) return FALSE; lstrcat(szJobFile, TEXT("\\Tasks\\\0")); LoadString(hInstApp, STR_JOB_NAME, szDefaultJobName, MAX_PATH); // If this is NT we need to append the user profile name onto the
// end of this task.
if (IsPlatformNT()) BuildNTJobName(szDefaultJobName); lstrcat(szJobFile, szDefaultJobName); DeleteFile(szJobFile); return TRUE; }
//---------------------------------------------------------------------------
// GetUserToken - Gets the current process's user token and returns
// it. It can later be free'd with LocalFree.
//---------------------------------------------------------------------------
PTOKEN_USER GetUserToken(HANDLE hUser) { PTOKEN_USER pUser; DWORD dwSize = 64; HANDLE hToClose = NULL;
if (hUser == NULL) { OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hUser); hToClose = hUser; }
pUser = (PTOKEN_USER)LocalAlloc(LPTR, dwSize); if (pUser) { DWORD dwNewSize; BOOL fOk = GetTokenInformation(hUser, TokenUser, pUser, dwSize, &dwNewSize); if (!fOk && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { LocalFree((HLOCAL)pUser);
pUser = (PTOKEN_USER)LocalAlloc(LPTR, dwNewSize); if (pUser) { fOk = GetTokenInformation( hUser, TokenUser, pUser, dwNewSize, &dwNewSize); } } if (!fOk) { LocalFree((HLOCAL)pUser); pUser = NULL; } }
if (hToClose) CloseHandle(hToClose);
return pUser; }
//----------------------------------------------------------------------------
// GetCurrentUser - Fills in a buffer with the unique name that we are using
// for the currently logged on user. On NT, this name is
// used for the name of the profile directory and for the
// name of the per-user recycle bin directory on a security
// aware drive.
//
// Parameters:
// lpAccountName -- buffer to receive user account name
// lpDomainName -- buffer to receive domain name
// lpProfilePath -- receives fully qualified path to user's
// profile directory. If the caller does
// not want the profile path NULL may be
// passed in for this parameter.
//----------------------------------------------------------------------------
extern "C" BOOL GetCurrentUser(LPTSTR lpAccountName, DWORD cchAcctSize, LPTSTR lpDomainName, DWORD cchDomSize, LPTSTR lpProfilePath, DWORD cchProfSize) { PTOKEN_USER pUser; LPTSTR pTextSid = 0; DWORD cbBytes; SID_NAME_USE SNU; HANDLE hUser;
// Take the easy outs -- no NULL parms for first four.
if (!lpAccountName || !lpDomainName || !&cchAcctSize || !&cchDomSize) return FALSE;
// Initialize these strings to NULL.
*lpAccountName = 0; *lpDomainName = 0;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hUser)) { return FALSE; }
pUser = GetUserToken(hUser);
CloseHandle(hUser);
if (!pUser) return FALSE;
if (!IsValidSid(pUser->User.Sid)) { LocalFree(pUser); return FALSE; }
if (!LookupAccountSid(NULL, pUser->User.Sid, lpAccountName, &cchAcctSize, lpDomainName, &cchDomSize, &SNU)) { // LookupAccountSid failed
LocalFree(pUser); return FALSE; }
// Does the caller want the profile path?
if (!lpProfilePath) { // No, so cleanup and hit the road.
LocalFree(pUser); return TRUE; }
// Have the Account and Domain Name. Next we need to get
// a text based SID so we can lookup the profile path in
// the registry.
// First let's find out how big a buffer we need for the
// text Sid.
*lpProfilePath = 0; cbBytes = 0; if ((!GetTextualSid(pUser->User.Sid, pTextSid, &cbBytes)) && (ERROR_INSUFFICIENT_BUFFER == GetLastError())) { pTextSid = (LPTSTR)LocalAlloc(LPTR, cbBytes); if (!pTextSid) { LocalFree(pUser); return FALSE; }
if (!GetTextualSid(pUser->User.Sid, pTextSid, &cbBytes)) { LocalFree(pUser); return FALSE; } } else { // Failed to get a text SID so we're outta here.
LocalFree((HLOCAL)pUser); return FALSE; }
// OK, now we should have a text-based SID. Used this to find
// the profilepath in the registry.
if (pTextSid) { HKEY hkeyProfileList;
// Open the registry and find the appropriate name
LONG lStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"), 0, KEY_READ, &hkeyProfileList);
if (lStatus == ERROR_SUCCESS) { HKEY hkeyUser; lStatus = RegOpenKeyEx(hkeyProfileList, pTextSid, 0, KEY_READ, &hkeyUser); if (lStatus == ERROR_SUCCESS) { DWORD dwType; cbBytes = (cchProfSize * sizeof(TCHAR));
// First check for a "ProfileName" key
lStatus = RegQueryValueEx(hkeyUser, TEXT("ProfileName"), NULL, &dwType, (LPBYTE)lpProfilePath, &cbBytes);
if (lStatus == ERROR_SUCCESS && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) { // We're good to go.
LocalFree(pUser); LocalFree(pTextSid); RegCloseKey(hkeyProfileList); RegCloseKey(hkeyUser); return TRUE; } else { // Otherwise, grab the "ProfilePath" and get the last part of the name
cbBytes = (cchProfSize * sizeof(TCHAR));
lStatus = RegQueryValueEx(hkeyUser,TEXT("ProfileImagePath"), NULL, &dwType, (LPBYTE)lpProfilePath, &cbBytes);
if (lStatus == ERROR_SUCCESS && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) { // Return just the directory name portion of the profile path
//lstrcpyn(lpBuff, PathFindFileName(lpProfilePath), iSize);
LocalFree(pUser); LocalFree(pTextSid); RegCloseKey(hkeyProfileList); RegCloseKey(hkeyUser); return TRUE; } else { // Have exhausted our resources -- can't get the
// profile path.
LocalFree(pUser); LocalFree(pTextSid); RegCloseKey(hkeyProfileList); RegCloseKey(hkeyUser); return FALSE; } } } else { // Couldn't open reg key so we're hosed
LocalFree(pUser); LocalFree(pTextSid); RegCloseKey(hkeyProfileList); return FALSE; } }
LocalFree(pUser); LocalFree(pTextSid);
} else { // For some completely unknown reason we have a NULL Sid string
// so we're doomed.
LocalFree(pTextSid); return FALSE; }
// We should never fall through to this point but if we do...
return FALSE; }
//+--------------------------------------------------------------------------
//
// Function: GetTextualSid()
//
// Synopsis: WINNT only -- converts a SID to text.
//
// Returns: TRUE if successful, FALSE if not.
// Sets LastError on failure.
//
// Taken from the January 1998 MSDN reference.
//
//---------------------------------------------------------------------------
BOOL GetTextualSid( PSID pSid, // binary Sid
LPTSTR TextualSid, // buffer for Textual representation of Sid
LPDWORD lpdwBufferLen) // required/provided TextualSid buffersize
{ PSID_IDENTIFIER_AUTHORITY psia; DWORD dwSubAuthorities; DWORD dwSidRev=SID_REVISION; DWORD dwCounter; DWORD dwSidSize;
// Validate the binary SID.
if(!IsValidSid(pSid)) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; }
// Get the identifier authority value from the SID.
psia = GetSidIdentifierAuthority(pSid);
// Get the number of subauthorities in the SID.
dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
// Compute the buffer length.
// S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL
dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
// Check input buffer length.
// If too small, indicate the proper size and set last error.
if (*lpdwBufferLen < dwSidSize) { *lpdwBufferLen = dwSidSize; SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; }
// Add 'S' prefix and revision number to the string.
dwSidSize=wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev );
// Add SID identifier authority to the string.
if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) ) { dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid), TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"), (USHORT)psia->Value[0], (USHORT)psia->Value[1], (USHORT)psia->Value[2], (USHORT)psia->Value[3], (USHORT)psia->Value[4], (USHORT)psia->Value[5]); } else { dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid), TEXT("%lu"), (ULONG)(psia->Value[5] ) + (ULONG)(psia->Value[4] << 8) + (ULONG)(psia->Value[3] << 16) + (ULONG)(psia->Value[2] << 24) ); }
// Add SID subauthorities to the string.
//
for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++) { dwSidSize+=wsprintf(TextualSid + dwSidSize, TEXT("-%lu"), *GetSidSubAuthority(pSid, dwCounter) ); }
SetLastError(ERROR_INSUFFICIENT_BUFFER); return TRUE; }
extern "C" VOID BuildNTJobName(LPTSTR lpJobName) { TCHAR szUser[MAX_PATH]; TCHAR szDomain[MAX_PATH]; TCHAR szProfile[MAX_PATH]; LPTSTR Current; LPTSTR Dot;
if (!lpJobName) return; // Null pointers not allowed.
if (!GetCurrentUser(szUser, ARRAYSIZE(szUser), szDomain, ARRAYSIZE(szDomain), szProfile, ARRAYSIZE(szProfile))) { // GetCurrentUser failed so bail out.
return; } // Walk to the end of the lpJobName string
Dot = lpJobName; while (*Dot) Dot = CharNext(Dot);
// Dot now points to the end of the lpJobName string. Backup until
// we get to the "dot" in the extension.
Dot = CharPrev(lpJobName, Dot); while ((Dot > lpJobName) && (*Dot != TEXT('.'))) Dot = CharPrev(lpJobName, Dot);
// Ok truncate the extension by putting a NULL on the "dot".
*Dot = TEXT('\0');
// Walk to the end of the szProfile string
Current = szProfile; while (*Current) Current = CharNext(Current);
// Current now points to the end of szProfile. Backup until we get
// to the first "\".
Current = CharPrev(szProfile, Current); while ((Current > szProfile) && (*Current != TEXT('\\'))) Current = CharPrev(szProfile, Current);
*Current = TEXT('(');
lstrcat(lpJobName, TEXT(" ")); lstrcat(lpJobName, Current); lstrcat(lpJobName, TEXT(").JOB")); }
extern "C" BOOL IsUserAdmin(VOID)
/*++
Routine Description:
This routine returns TRUE if the caller's process is a member of the Administrators local group.
Caller is NOT expected to be impersonating anyone and IS expected to be able to open their own process and process token.
Arguments:
None.
Return Value:
TRUE - Caller has Administrators local group.
FALSE - Caller does not have Administrators local group.
--*/
{ HANDLE Token; DWORD BytesRequired; PTOKEN_GROUPS Groups; BOOL b; DWORD i; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; PSID AdministratorsGroup;
//
// On non-NT platforms the user is administrator.
//
if(!IsPlatformNT()) { return(TRUE); }
//
// Open the process token.
//
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&Token)) { return(FALSE); }
b = FALSE; Groups = NULL;
//
// Get group information.
//
if (!GetTokenInformation(Token,TokenGroups,NULL,0,&BytesRequired) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER) && (Groups = (PTOKEN_GROUPS)LocalAlloc(LPTR,BytesRequired)) && GetTokenInformation(Token,TokenGroups,Groups,BytesRequired,&BytesRequired)) {
b = AllocateAndInitializeSid( &NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup );
if (b) {
//
// See if the user has the administrator group.
//
b = FALSE; for(i=0; i<Groups->GroupCount; i++) { if(EqualSid(Groups->Groups[i].Sid,AdministratorsGroup)) { b = TRUE; break; } }
FreeSid(AdministratorsGroup); } }
//
// Clean up and return.
//
if(Groups) { LocalFree((HLOCAL)Groups); }
CloseHandle(Token);
return(b); }
|