/**
 * Set a Task into task scheduler. It takes values to insert from Schedule form.
 * If task already exists, it is updated with passed parameters.
 * Starting time is always set to current time (task starts now).
 *
 * @param frequency : NEVER or EVERY_DAY
 * @param dayNum    : repeate the task every 'dayNum'
 * @param minNum    : repeate the task every 'minNum'
 * @return            0 if no errors.
 */
int setScheduleTask (const char* frequency, const int dayNum, const int minNum) {

    HRESULT hr = S_OK;
    bool newTask = false;
    ITaskScheduler* pITS = NULL;
    ITask*          pITask;
    IPersistFile*   pIPersistFile;
    wstring taskName, user;

    // Init COM library & create instance for Task scheduler.
    if ((pITS = initScheduleInstance()) == NULL) {
        goto error;
    }

    // Task is associated with current user
    if (getScheduledTaskName(taskName)) {
        goto error;
    }

    // We need the extended username "MACHINE\USER" to ensure that
    // the job can run also for users logged in with another domain (ref bug #307010).
    if (getWindowsUserEx(user)) {
        goto error;
    }

    //
    // Try to open EXISTING TASK.
    //
    LOG.debug("Try opening the Windows task: \"%ls\"", taskName.c_str());
    hr = pITS->Activate(taskName.c_str(),
                        IID_ITask,
                        (IUnknown**) &pITask);
    
    if (FAILED(hr)) {
        if (hr == E_OBJECT_NOT_FOUND) {
            //
            // NEW TASK -> create it.
            //
            LOG.debug(DBG_SCHED_TASK_NOT_FOUND);
            newTask = true;

            WCHAR path[512];
            OutlookConfig* config = OutlookConfig::getInstance();
            // Get current working dir (from config)
            const char* t = config->getWorkingDir();
            WCHAR* wt = toWideChar(t);
            wsprintf(path, TEXT("\"%s\\%s\""), wt, TEXT(PROGRAM_NAME_EXE));
            delete [] wt;  wt = NULL;

            hr = pITS->NewWorkItem(taskName.c_str(),       // Name of task
                                   CLSID_CTask,            // Class identifier
                                   IID_ITask,              // Interface identifier
                                   (IUnknown**)&pITask);   // Address of task interface
            if (FAILED(hr)) {
                char* msg = readSystemErrorMsg(hr);
                setErrorF(getLastErrorCode(), ERR_SCHED_NEWWORKITEM, hr, msg);
                delete [] msg;
                pITS->Release();
                goto error;
            }

            // Set path and comment on new task.
            pITask->SetApplicationName(path);
            pITask->SetComment(SCHED_COMMENT);
        }
        else {
            char* msg = readSystemErrorMsg(hr);
            setErrorF(getLastErrorCode(), ERR_SCHED_ACTIVATE, hr, msg);
            delete [] msg;
            pITS->Release();
            goto error;
        }
    }
    pITS->Release();


    //
    // Set task params: flags, account info, parameters
    if (strcmp(NEVER, frequency) == 0) {
        pITask->SetFlags(TASK_FLAG_DISABLED);
    } 
    else {
        pITask->SetAccountInformation(user.c_str(), NULL);
        pITask->SetFlags(TASK_FLAG_INTERACTIVE | TASK_FLAG_RUN_ONLY_IF_LOGGED_ON);
    }

    // ...so we have "OutlookPlugin.exe schedule"    
    pITask->SetParameters(SCHED_PARAM);


    //
    // Get/create the trigger object.
    //
    ITaskTrigger *pITaskTrigger;
    if (newTask) {
        WORD piNewTrigger;
        hr = pITask->CreateTrigger(&piNewTrigger, &pITaskTrigger);
        if (FAILED(hr)) {
            char* msg = readSystemErrorMsg(hr);
            setErrorF(getLastErrorCode(), ERR_SCHED_CREATE_TRIGGER, hr, msg);
            delete [] msg;
            goto error;
        }
    }
    else {
        hr = pITask->GetTrigger(0, &pITaskTrigger);
        if (FAILED(hr)) {
            char* msg = readSystemErrorMsg(hr);
            setErrorF(getLastErrorCode(), ERR_SCHED_GET_TRIGGER, hr, msg);
            delete [] msg;
            goto error;
        }
    }

    //////////////////////////////////////////////////////
    // Define TASK_TRIGGER structure.
    // Start time is derived from NOW.
    //////////////////////////////////////////////////////
    TASK_TRIGGER pTrigger;
    ZeroMemory(&pTrigger, sizeof (TASK_TRIGGER));

    time_t timer;
    time(&timer);
    struct tm* now = localtime(&timer);

    int minToSet = minNum;
    if (minToSet == 1440) {
        minToSet = 1439;   // this because the windows scheduler thrown an error if
                            // the value is a day
    }

    pTrigger.wBeginDay                = now->tm_mday;               // START = NOW.
    // TASK_TRIGGER uses wBeginMonth in interval (1,12), but tm_mon is in interval (0,11)
    pTrigger.wBeginMonth              = now->tm_mon + 1;
    pTrigger.wBeginYear               = now->tm_year + 1900;        // 'struct tm' has year from 1900...
    pTrigger.wStartHour               = now->tm_hour;
    pTrigger.wStartMinute             = now->tm_min - 1;            // -1 to avoid starting a sync right now!

    pTrigger.cbTriggerSize = sizeof (TASK_TRIGGER) ;
    pTrigger.MinutesDuration          = 1440;                       // Duration = fixed 1 day.
    pTrigger.MinutesInterval          = minToSet;
    pTrigger.TriggerType              = TASK_TIME_TRIGGER_DAILY;    // Manage only DAILY schedules!
    pTrigger.Type.Daily.DaysInterval  = dayNum;
    //////////////////////////////////////////////////////

    //
    // Set trigger criteria.
    //
    hr = pITaskTrigger->SetTrigger(&pTrigger);
    if (FAILED(hr)) {
        if (hr == E_INVALIDARG) {
            setErrorF(getLastErrorCode(), ERR_SCHED_SET_TRIGGER, hr, ERR_SCHED_INVALID_PARAM);
        }
        else {
            char* msg = readSystemErrorMsg(hr);
            setErrorF(getLastErrorCode(), ERR_SCHED_SET_TRIGGER, hr, msg);
            delete [] msg;
        }
        goto error;
    }

    //
    // Call IUnknown::QueryInterface to get a pointer to IPersistFile.
    //
    hr = pITask->QueryInterface(IID_IPersistFile, (void **)&pIPersistFile);
    if (FAILED(hr)) {
        char* msg = readSystemErrorMsg(hr);
        setErrorF(getLastErrorCode(), ERR_SCHED_QUERY_INTERFACE, hr, msg);
        delete [] msg;
        goto error;
    }
    pITask->Release();
    pITaskTrigger->Release();

    //
    // Save the task to disk.
    //
    hr = pIPersistFile->Save(NULL, TRUE);
    if (FAILED(hr)) {
        char* msg = readSystemErrorMsg(hr);
        setErrorF(getLastErrorCode(), ERR_SCHED_SAVE, hr, msg);
        delete [] msg;
        goto error;
    }
    pIPersistFile->Release();

    LOG.info(INFO_SCHED_TASK_CREATED);
    CoUninitialize();
    return 0;


error:
    CoUninitialize();
    LOG.error(getLastErrorMsg());
    return 1;
}
Exemplo n.º 2
0
HRESULT CScheduledTask::SaveTask ( LPCTSTR szTaskName,
                                   BOOL    bFailIfExists /*=FALSE*/ ) const
{
HRESULT         hr;
ITaskScheduler* pISched    = NULL;
IUnknown*       pIUnk      = NULL;
IPersistFile*   pIFile     = NULL;
ITask*          pITask     = NULL;
ITaskTrigger*   pITaskTrig = NULL;
TASK_TRIGGER    rTrigger;
DWORD           dwTaskFlags;
WORD            wTrigNumber;

    USES_CONVERSION;

    ASSERT ( AfxIsValidString ( szTaskName ));

    // Get an interface to the scheduler.

    hr = ::CoCreateInstance (
               CLSID_CTaskScheduler,
               NULL,
               CLSCTX_INPROC_SERVER,
               IID_ITaskScheduler,
               (void **) &pISched );


    if ( FAILED(hr) )
        {
#ifdef _DEBUG
        TRACE1("CScheduledTask::SaveTask() - failed to create a task scheduler interface. Return = 0x%08X\n",
               (DWORD) hr );
        
        // Check if the error was "class not registered".  If so, you don't
        // have the scheduler installed.  I display a nice long message in
        // the debug window, which hopefully explains what's up. :)

        if ( REGDB_E_CLASSNOTREG == hr )
            {
            TRACE0("    The error was REGDB_E_CLASSNOTREG, meaning you don't have the scheduler installed.\n"
                _T("    If you are running 95 or NT 4 with IE 4, you must install the task scheduler from the\n")
                _T("    IE components install page on MS's web site or the IE CD.\n")
                _T("    If you're on 98, NT 5, or 95/NT 4 with IE 5, then something's wrong with your install\n")
                _T("    because the scheduler should always be installed.\n")
                _T("    Note that this class does *NOT* work with the \"AT\" service, which is the default\n")
                _T("    scheduler on NT 4 and earlier.\n") );
            }
#endif  // _DEBUG

        return hr;
        }


__try
    {
    // Check if a task with the given name already exists in the scheduler.
    // I do this check manually because the behavior of 
    // ITaskScheduler::NewWorkItem() is different between IE 4 and IE 5.
    // In IE 4, NewWorkItem() will succeed if a task with the name you pass it
    // already exists (even though the INetSDK docs says it should fail).
    // In IE 5, NewWorkItem() has been fixed to match the docs.
    // So, my solution is to call ITaskScheduler::Activate() and pass it the
    // task name.  If that function succeeds, then I know a task with the
    // given name already exists.
    // (Note to MS: This _really_ ought to be mentioned in the KB!!)

    hr = pISched->Activate ( T2COLE ( szTaskName ), IID_ITask, &pIUnk );

    if ( SUCCEEDED(hr) )
        {
        // A task with the given name already exists.  Check bFailIfExists
        // to see what we should do.

        pIUnk->Release();               // We don't need this interface.
        pIUnk = NULL;

        if ( bFailIfExists )
            {
            TRACE0("CScheduledTask::SaveTask() - A task with the given name already exists; failing.\n");
            return HRESULT_FROM_WIN32 ( ERROR_FILE_EXISTS );
            }
        else
            {
            // Try to delete the existing task.  If the delete succeeds, then
            // we proceed.  Otherwise, we'll bail out with an error.

            TRACE0("CScheduledTask::SaveTask() - A task with the given name already exists; deleting it.\n");

            hr = CScheduledTask::DeleteTask ( szTaskName );

            if ( FAILED(hr) )
                {
                TRACE1("CScheduledTask::SaveTask() - couldn't delete existing task! Bailing out. Return = 0x%08X\n",
                       (DWORD) hr );
                return hr;
                }
            }
        }


    // Create a new task.

    hr = pISched->NewWorkItem ( T2COLE ( szTaskName ), CLSID_CTask,
                                IID_ITask, &pIUnk );

    if ( FAILED(hr) )
        {
        TRACE1("CScheduledTask::SaveTask() - couldn't create a new work item. Return = 0x%08X\n",
               (DWORD) hr );
        return hr;
        }


    // We now have an IUnknown pointer.  This is queried for an ITask
    // pointer on the work item we just added.
    
    hr = pIUnk->QueryInterface ( IID_ITask, (void **) &pITask );

    if ( FAILED(hr) )
        {
        TRACE1("CScheduledTask::SaveTask() - QI() on IUnknown failed to get an ITask. Return = 0x%08X\n",
               (DWORD) hr );
        return hr;
        }
    

    // Clean up the IUnknown, as we are done with it.
    
    pIUnk->Release();
    pIUnk = NULL;


    // Set the program name.

    hr = pITask->SetApplicationName ( T2COLE( (LPCTSTR) m_sProgramPath ));

    if ( FAILED(hr) )
        {
        TRACE1("CScheduledTask::SaveTask() - failed to set application. Return = 0x%08X\n",
               (DWORD) hr );
        return hr;
        }


    // Set the app's parameters.

    if ( m_sParameters.GetLength() > 0 )
        {
        hr = pITask->SetParameters ( T2COLE( (LPCTSTR) m_sParameters ));

        if ( FAILED(hr) )
            {
            TRACE1("CScheduledTask::SaveTask() - failed to set parameters. Return = 0x%08X\n",
                   (DWORD) hr );
            return hr;
            }
        }        


    // Set the starting directory.

    if ( m_sStartingDir.GetLength() > 0 )
        {
        hr = pITask->SetWorkingDirectory ( T2COLE( (LPCTSTR) m_sStartingDir ));

        if ( FAILED(hr) )
            {
            TRACE1("CScheduledTask::SaveTask() - failed to set starting directory. Return = 0x%08X\n",
                   (DWORD) hr );
            return hr;
            }
        }


	TCHAR infoBuf[32767];
	DWORD bufCharCount = 32767;

	GetUserNameEx(NameSamCompatible, infoBuf, &bufCharCount);
	hr = pITask->SetAccountInformation((LPCWSTR)infoBuf, L"");

    // Set the job comment.

    if ( m_sComment.GetLength() > 0 )
        {
        hr = pITask->SetComment ( T2COLE( (LPCTSTR) m_sComment ));

        if ( FAILED (hr) )
            {
            TRACE1("CScheduledTask::SaveTask() - failed to set task comment. Return = 0x%08X\n",
                   (DWORD) hr );
            return hr;
            }
        }

    //TCHAR pszName[CREDUI_MAX_USERNAME_LENGTH] = "";
    //TCHAR pszPwd[CREDUI_MAX_PASSWORD_LENGTH] = "";

  ///////////////////////////////////////////////////////////////////
  // Call ITask::SetAccountInformation to specify the account name
  // and the account password for Test Task.
  ///////////////////////////////////////////////////////////////////
  //hr = pITask->SetAccountInformation((LPCWSTR)pszName, 
  //          (LPCWSTR)pszPwd);

  //SecureZeroMemory(pszName, sizeof(pszName));
  //SecureZeroMemory(pszPwd, sizeof(pszPwd));
  


    // Set the flags on the task object
    
    // The two flags below are the default for events created via the task 
    // scheduler UI.
    // Note that I _don't_ set TASK_FLAG_DELETE_WHEN_DONE.  Setting this flag
    // is bad if you have the "Notify me of missed tasks" option on in the
    // scheduler.  If this flag is set and the event is missed, the scheduler
    // nukes the event without notifying you .  How mean.

    dwTaskFlags = TASK_FLAG_RUN_ONLY_IF_LOGGED_ON;

    // On NT, set the interactive flag so the user can see it.
    if ( !( GetVersion() & 0x80000000 ) )
        {
        dwTaskFlags |= TASK_FLAG_INTERACTIVE;
        }

    hr = pITask->SetFlags ( dwTaskFlags );

    if ( FAILED (hr) )
        {
        TRACE1("CScheduledTask::SaveTask() - failed to set task flags. Return = 0x%08X\n",
               (DWORD) hr );
        return hr;
        }


    // Now, create a trigger to run the task at our specified time.

    hr = pITask->CreateTrigger ( &wTrigNumber, &pITaskTrig );

    if ( FAILED (hr) )
        {
        TRACE1("CScheduledTask::SaveTask() - failed to create a task trigger. Return = 0x%08X\n",
               (DWORD) hr );
        return hr;
        }


    // Now, fill in the trigger as necessary.  Note that the seconds field of
    // m_timeStart is not used since the scheduler only stores the hour
    // and minute of the starting time.

    ZeroMemory ( &rTrigger, sizeof (TASK_TRIGGER) );

    rTrigger.cbTriggerSize = sizeof (TASK_TRIGGER);
    rTrigger.wBeginYear    = m_timeStart.wYear;
    rTrigger.wBeginMonth   = m_timeStart.wMonth;
    rTrigger.wBeginDay     = m_timeStart.wDay;
    rTrigger.wStartHour    = m_timeStart.wHour;
    rTrigger.wStartMinute  = m_timeStart.wMinute;

    if ( 0 != m_timeEnd.wYear )
        {
        rTrigger.rgFlags   = TASK_TRIGGER_FLAG_HAS_END_DATE;
        rTrigger.wEndYear  = m_timeEnd.wYear;
        rTrigger.wEndMonth = m_timeEnd.wMonth;
        rTrigger.wEndDay   = m_timeEnd.wDay;
        }


    switch ( m_eFreq )
        {
        case freqOnce: 
            rTrigger.TriggerType = TASK_TIME_TRIGGER_ONCE;
        break;
        
        case freqDaily:
            rTrigger.TriggerType = TASK_TIME_TRIGGER_DAILY;

            // Repeat every day.
            rTrigger.Type.Daily.DaysInterval = 1;
        break;

        case freqWeekly:
            rTrigger.TriggerType = TASK_TIME_TRIGGER_WEEKLY;

            rTrigger.Type.Weekly.rgfDaysOfTheWeek = 
                GetDayOfWeekFlag ( m_timeStart );

            // Repeat every week.
            rTrigger.Type.Weekly.WeeksInterval = 1;
        break;

        case freqMonthly:
            rTrigger.TriggerType = TASK_TIME_TRIGGER_MONTHLYDATE;

            rTrigger.Type.MonthlyDate.rgfDays = 1 << ( m_timeStart.wDay - 1 );
            rTrigger.Type.MonthlyDate.rgfMonths = DDS_CST_EVERYMONTH;
        break;

        DEFAULT_UNREACHABLE;
        }


    // Add this trigger to the task using ITaskTrigger::SetTrigger

    hr = pITaskTrig->SetTrigger ( &rTrigger );

    if ( FAILED(hr) )
        {
        TRACE1("CScheduledTask::SaveTask() - failed to add trigger to the task. Return = 0x%08X\n",
               (DWORD) hr );
        return hr;
        }


    // Save the changes with IPersistFile::SaveTask().  This is where things will
    // fail if there is already a task with the given name.

    hr = pITask->QueryInterface ( IID_IPersistFile, (void **) &pIFile );

    if ( FAILED (hr) )
        {
        TRACE1("CScheduledTask::SaveTask() - failed to get an IPersistFile interface on the task. Return = 0x%08X\n",
               (DWORD) hr );
        return hr;
        }

    hr = pIFile->Save ( NULL, FALSE );

    if ( FAILED(hr) )
        {
        TRACE1("CScheduledTask::SaveTask() - error saving task. Return = 0x%08X\n",
               (DWORD) hr );
        return hr;
        }

    }   // end __try
__finally
    {
    // Clean up all the interfaces.
    
    if ( pIFile != NULL )
        pIFile->Release();

    if ( pITaskTrig != NULL )
        pITaskTrig->Release();

    if ( pITask != NULL )
        pITask->Release();

    if ( pISched != NULL )
        pISched->Release();

    }   // end __finally

    return hr;
}
/**
 * Get task info from Task scheduler.
 * Returns 0 if task found and no errors, -1 if task not found.
 * If task found: frequency, dayNum, minNum and statusCode are set.
 *
 * @param active  : [OUT] true if task is active
 * @param dayNum  : [OUT] repeating every 'dayNum' days
 * @param minNum  : [OUT] repeating every 'minNum' minutes
 * @return          0 = task found, status correct.
 *                  1 = task found, status incorrect.
 *                  2 = task found but manually changed.
 *                 -1 = task not found.
 *                 -2 = errors occurred.
 */
int getScheduleTask(bool* active, int* dayNum, int* minNum) {

    int ret = 0;
    HRESULT hr = S_OK;
    ITaskScheduler* pITS = NULL;
    ITask*          pITask;
    wstring taskName;

    // Init COM library & create instance for Task scheduler.
    if ((pITS = initScheduleInstance()) == NULL) {
        goto error;
    }

    // Task is associated with current user
    if (getScheduledTaskName(taskName)) {
        goto error;
    }

    //
    // Open the task (fails if task not existing).
    //
    hr = pITS->Activate(taskName.c_str(),
                        IID_ITask,
                        (IUnknown**) &pITask);
    pITS->Release();
    if (FAILED(hr)) {
        goto notExisting;
    }


    //
    // Check task status
    //
    DWORD pdwExitCode;
    hr = pITask->GetExitCode(&pdwExitCode);
    if ((hr & SCHED_S_TASK_HAS_NOT_RUN) || (hr != S_OK)) {
        setErrorF(getLastErrorCode(), DBG_SCHED_LAST_EXECUTION);
        LOG.debug(getLastErrorMsg());
        ret = 1;
    }


    //
    // Check the flags -> active/disabled
    //
    DWORD flag = -1, triggerType = -1;
    pITask->GetFlags(&flag);
    if (flag & TASK_FLAG_DISABLED) {
        *active = false;
    } else {
        *active = true;
    }


    //
    // Get the trigger interface.
    //
    ITaskTrigger *pITaskTrigger;
    hr = pITask->GetTrigger(0, &pITaskTrigger);
    if (FAILED(hr)) {
        char* msg = readSystemErrorMsg(hr);
        setErrorF(getLastErrorCode(), ERR_SCHED_GET_TRIGGER, hr, msg);
        delete [] msg;
        goto error;
    }

    TASK_TRIGGER pTrigger;
    ZeroMemory(&pTrigger, sizeof(TASK_TRIGGER));
    hr = pITaskTrigger->GetTrigger(&pTrigger);
    if (FAILED(hr)) {
        char* msg = readSystemErrorMsg(hr);
        setErrorF(getLastErrorCode(), ERR_SCHED_GET_TRIGGER2, hr, msg);
        delete [] msg;
        goto error;
    }

    //
    // Get values
    //
    int minToSet = pTrigger.MinutesInterval;
    if (minToSet == 1439) {
        minToSet = 1440;    // the value must normalized to get 1 day
    }

    *minNum = minToSet; // pTrigger.MinutesInterval;
    *dayNum = pTrigger.Type.Daily.DaysInterval;

    // Check if trigger correct
    triggerType = pTrigger.TriggerType;
    if (triggerType != TASK_TIME_TRIGGER_DAILY ||
        (pTrigger.MinutesDuration != 0
         && pTrigger.MinutesInterval != 0
         && pTrigger.MinutesDuration != 1440) ) {
        ret = 2;
    }

    // Release the ITask interface.
    pITaskTrigger->Release();
    pITask->Release();

    CoUninitialize();
    return ret;

notExisting:
    LOG.debug(DBG_SCHED_TASK_NOT_FOUND);
    *active = false;
    *minNum = 0;
    *dayNum = 0;
    CoUninitialize();
    return -1;

error:
    LOG.error(getLastErrorMsg());
    CoUninitialize();
    return -2;
}
Exemplo n.º 4
0
HRESULT CTask::SaveTask ( LPCTSTR szTaskName,
                                   BOOL    bFailIfExists /*=FALSE*/ ) const
{
HRESULT         hr;
ITaskScheduler* pISched    = NULL;
IUnknown*       pIUnk      = NULL;
IPersistFile*   pIFile     = NULL;
ITask*          pITask     = NULL;
ITaskTrigger*   pITaskTrig = NULL;
TASK_TRIGGER    rTrigger;
DWORD           dwTaskFlags;
WORD            wTrigNumber;

    USES_CONVERSION;

    ASSERT ( AfxIsValidString ( szTaskName ));
    // Sciezka programu nie moze byc pusta, ale inne moga

    if ( 0 == m_timeStart.wYear      ||
         NULL == szTaskName          ||
         0 == lstrlen ( szTaskName ) ||
         m_sProgramPath.GetLength() < 1 )
        {
        return E_FAIL;
        }


    // Pobieramy interface IScheduler
    hr = ::CoCreateInstance (
               CLSID_CTaskScheduler,
               NULL,
               CLSCTX_INPROC_SERVER,
               IID_ITaskScheduler,
               (void **) &pISched );


    if ( FAILED(hr) )
        {
#ifdef _DEBUG
        TRACE1("CTask::SaveTask() - failed to create a task scheduler interface. Return = 0x%08X\n",
               (DWORD) hr );

	// Harmonogram zadan nie zostal zainstalowany lub zostal odinstalowany
        if ( REGDB_E_CLASSNOTREG == hr )
            {
            TRACE0("    The error was REGDB_E_CLASSNOTREG, meaning you don't have the scheduler installed.\n"
                _T("    If you are running 95 or NT 4 with IE 4, you must install the task scheduler from the\n")
                _T("    IE components install page on MS's web site or the IE CD.\n")
                _T("    If you're on 98, NT 5, or 95/NT 4 with IE 5, then something's wrong with your install\n")
                _T("    because the scheduler should always be present.\n")
                _T("    Note that this class does *NOT* work with the \"AT\" service, which is the default\n")
                _T("    scheduler on NT 4 and earlier.\n") );
            }
#endif  // _DEBUG

        return hr;
        }


__try
    {
    

//sprawdz czy zadanie o podanek przez uzytkownika nazwie istnieje
    hr = pISched->Activate ( T2COLE ( szTaskName ), IID_ITask, &pIUnk );

    if ( SUCCEEDED(hr) )
        {
        
	//zadanie o podanej nazwie juz istnieje, sprawdzmy bFailIfExists.

        pIUnk->Release();               // zwalniamy interfejs
        pIUnk = NULL;

        if ( bFailIfExists )
            {
            TRACE0("CTask::SaveTask() - A task with the given name already exists; failing.\n");
            return HRESULT_FROM_WIN32 ( ERROR_FILE_EXISTS );
            }
        else
            {
           	//probujemy usunac istniejace zadanie, by zrobic miejsce dla naszego.
            TRACE0("CTask::SaveTask() - A task with the given name already exists; deleting it.\n");

            hr = CTask::DeleteTask ( szTaskName );

            if ( FAILED(hr) )
                {
                TRACE1("CTask::SaveTask() - couldn't delete existing task! Bailing out. Return = 0x%08X\n",
                       (DWORD) hr );
                return hr;
                }
            }
        }


    // tworzymy nowe zadanie.
    hr = pISched->NewWorkItem ( T2COLE ( szTaskName ), CLSID_CTask,
                                IID_ITask, &pIUnk );

    if ( FAILED(hr) )
        {
        TRACE1("CTask::SaveTask() - couldn't create a new work item. Return = 0x%08X\n",
               (DWORD) hr );
        return hr;
        }

	//mamy wskaznik do IUnknown, odpytujemy go, aby uzyskac 
	//wskaznik do interfejsu ITask  
    hr = pIUnk->QueryInterface ( IID_ITask, (void **) &pITask );

    if ( FAILED(hr) )
        {
        TRACE1("CTask::SaveTask() - QI() on IUnknown failed to get an ITask. Return = 0x%08X\n",
               (DWORD) hr );
        return hr;
        }
    

    // wskaznika do IUnknown juz nie potrzebujemy  
    pIUnk->Release();
    pIUnk = NULL;


    // ustawiamy nazwe dla aplikacji
    hr = pITask->SetApplicationName ( T2COLE( (LPCTSTR) m_sProgramPath ));

    if ( FAILED(hr) )
        {
        TRACE1("CTask::SaveTask() - failed to set application. Return = 0x%08X\n",
               (DWORD) hr );
        return hr;
        }


    // ustawiamy parametry dla aplikacji
    if ( m_sParameters.GetLength() > 0 )
        {
        hr = pITask->SetParameters ( T2COLE( (LPCTSTR) m_sParameters ));

        if ( FAILED(hr) )
            {
            TRACE1("CTask::SaveTask() - failed to set parameters. Return = 0x%08X\n",
                   (DWORD) hr );
            return hr;
            }
        }        


    // ustawiamy folder startowy dla aplikacji
    if ( m_sStartingDir.GetLength() > 0 )
        {
        hr = pITask->SetWorkingDirectory ( T2COLE( (LPCTSTR) m_sStartingDir ));

        if ( FAILED(hr) )
            {
            TRACE1("CTask::SaveTask() - failed to set starting directory. Return = 0x%08X\n",
                   (DWORD) hr );
            return hr;
            }
        }


    // ustawiamy nazwe uzytkownika i haslo, jesli jestesmy na NT
    if ( m_bNT )
        {
        hr = pITask->SetAccountInformation ( T2COLE( (LPCTSTR) m_sAccount),
                                             T2COLE( (LPCTSTR) m_sPassword) );

        if ( FAILED(hr) )
            {
            TRACE1("CTask::SaveTask() - failed to set account info.  Return = 0x%08X\n",
                   (DWORD) hr );
            return hr;
            }
        }


    // ustawiamy komentarz do zadania
    if ( m_sComment.GetLength() > 0 )
        {
        hr = pITask->SetComment ( T2COLE( (LPCTSTR) m_sComment ));

        if ( FAILED (hr) )
            {
            TRACE1("CTask::SaveTask() - failed to set task comment. Return = 0x%08X\n",
                   (DWORD) hr );
            return hr;
            }
        }


    // ustawiamy flagi
    //zapraszam do eksperymentow z flaga TASK_FLAG_DELETE_WHEN_DONE...
    dwTaskFlags = TASK_FLAG_DONT_START_IF_ON_BATTERIES |
                  TASK_FLAG_KILL_IF_GOING_ON_BATTERIES;

    // na NT ustawimy flage interactive
    if ( !( GetVersion() & 0x80000000 ) )
        {
        dwTaskFlags |= TASK_FLAG_INTERACTIVE;
        }

    hr = pITask->SetFlags ( dwTaskFlags );

    if ( FAILED (hr) )
        {
        TRACE1("CTask::SaveTask() - failed to set task flags. Return = 0x%08X\n",
               (DWORD) hr );
        return hr;
        }


    // teraz tworzymy Trigger, czyli wyzwalacz
    hr = pITask->CreateTrigger ( &wTrigNumber, &pITaskTrig );

    if ( FAILED (hr) )
        {
        TRACE1("CTask::SaveTask() - failed to create a task trigger. Return = 0x%08X\n",
               (DWORD) hr );
        return hr;
        }


    //ustawimy parametry triggera
	//zwroc uwage ze sekundy sa ignorowane
    ZeroMemory ( &rTrigger, sizeof (TASK_TRIGGER) );

    rTrigger.cbTriggerSize = sizeof (TASK_TRIGGER);
    rTrigger.wBeginYear    = m_timeStart.wYear;
    rTrigger.wBeginMonth   = m_timeStart.wMonth;
    rTrigger.wBeginDay     = m_timeStart.wDay;
    rTrigger.wStartHour    = m_timeStart.wHour;
    rTrigger.wStartMinute  = m_timeStart.wMinute;

    if ( 0 != m_timeEnd.wYear )
        {
        rTrigger.rgFlags   = TASK_TRIGGER_FLAG_HAS_END_DATE;
        rTrigger.wEndYear  = m_timeEnd.wYear;
        rTrigger.wEndMonth = m_timeEnd.wMonth;
        rTrigger.wEndDay   = m_timeEnd.wDay;
        }


    switch ( m_eFreq )
        {
        case freqOnce: 
            rTrigger.TriggerType = TASK_TIME_TRIGGER_ONCE;
        break;
        
        case freqDaily:
            rTrigger.TriggerType = TASK_TIME_TRIGGER_DAILY;

        // codziennie.
            rTrigger.Type.Daily.DaysInterval = 1;
        break;

        case freqWeekly:
            rTrigger.TriggerType = TASK_TIME_TRIGGER_WEEKLY;

            rTrigger.Type.Weekly.rgfDaysOfTheWeek = 
                GetDayOfWeekFlag ( m_timeStart );

        // co tydzien.
            rTrigger.Type.Weekly.WeeksInterval = 1;
        break;

		//co miesiac.
        case freqMonthly:
            rTrigger.TriggerType = TASK_TIME_TRIGGER_MONTHLYDATE;

            rTrigger.Type.MonthlyDate.rgfDays = 1 << ( m_timeStart.wDay - 1 );
            rTrigger.Type.MonthlyDate.rgfMonths = DDS_CST_EVERYMONTH;
        break;

        DEFAULT_UNREACHABLE;
        }


    // skojarz Trigger z zadaniem
    hr = pITaskTrig->SetTrigger ( &rTrigger );

    if ( FAILED(hr) )
        {
        TRACE1("CTask::SaveTask() - failed to add trigger to the task. Return = 0x%08X\n",
               (DWORD) hr );
        return hr;
        }


    // zapisujemy zmiany w PersistFile
    hr = pITask->QueryInterface ( IID_IPersistFile, (void **) &pIFile );

    if ( FAILED (hr) )
        {
        TRACE1("CTask::SaveTask() - failed to get an IPersistFile interface on the task. Return = 0x%08X\n",
               (DWORD) hr );
        return hr;
        }

    hr = pIFile->Save ( NULL, FALSE );

    if ( FAILED(hr) )
        {
        TRACE1("CTask::SaveTask() - error saving task. Return = 0x%08X\n",
               (DWORD) hr );
        return hr;
        }

    }   // end __try
__finally
    {
    // sprzatamy  
    if ( pIFile != NULL )
        pIFile->Release();

    if ( pITaskTrig != NULL )
        pITaskTrig->Release();

    if ( pITask != NULL )
        pITask->Release();

    if ( pISched != NULL )
        pISched->Release();

    }   // end __finally

    return hr;
}