[PATCH 1/2] mstask: Implement ITask::GetNextRunTime() for ONCE trigger type.

Dmitry Timoshkov dmitry at baikal.ru
Mon May 21 05:17:47 CDT 2018


Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
 dlls/mstask/task.c               | 90 ++++++++++++++++++++++++++++++++++++++--
 dlls/mstask/tests/task_trigger.c | 81 +++++++++++++++++++++++++++++++++---
 2 files changed, 163 insertions(+), 8 deletions(-)

diff --git a/dlls/mstask/task.c b/dlls/mstask/task.c
index d487aeb5a5..c004764af0 100644
--- a/dlls/mstask/task.c
+++ b/dlls/mstask/task.c
@@ -408,11 +408,95 @@ static HRESULT WINAPI MSTASK_ITask_GetRunTimes(
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI MSTASK_ITask_GetNextRunTime(ITask *iface, SYSTEMTIME *st)
+static void get_begin_time(const TASK_TRIGGER *trigger, FILETIME *ft)
 {
-    FIXME("(%p, %p): stub\n", iface, st);
+    SYSTEMTIME st;
 
-    memset(st, 0, sizeof(*st));
+    st.wYear = trigger->wBeginYear;
+    st.wMonth = trigger->wBeginMonth;
+    st.wDay = trigger->wBeginDay;
+    st.wDayOfWeek = 0;
+    st.wHour = 0;
+    st.wMinute = 0;
+    st.wSecond = 0;
+    st.wMilliseconds = 0;
+    SystemTimeToFileTime(&st, ft);
+}
+
+static void get_end_time(const TASK_TRIGGER *trigger, FILETIME *ft)
+{
+    SYSTEMTIME st;
+
+    if (!(trigger->rgFlags & TASK_TRIGGER_FLAG_HAS_END_DATE))
+    {
+        ft->dwHighDateTime = ~0u;
+        ft->dwLowDateTime = ~0u;
+        return;
+    }
+
+    st.wYear = trigger->wEndYear;
+    st.wMonth = trigger->wEndMonth;
+    st.wDay = trigger->wEndDay;
+    st.wDayOfWeek = 0;
+    st.wHour = 0;
+    st.wMinute = 0;
+    st.wSecond = 0;
+    st.wMilliseconds = 0;
+    SystemTimeToFileTime(&st, ft);
+}
+
+static HRESULT WINAPI MSTASK_ITask_GetNextRunTime(ITask *iface, SYSTEMTIME *rt)
+{
+    TaskImpl *This = impl_from_ITask(iface);
+    SYSTEMTIME st, current_st;
+    FILETIME current_ft, begin_ft, end_ft, best_ft;
+    BOOL have_best_time = FALSE;
+    DWORD i;
+
+    TRACE("(%p, %p)\n", iface, rt);
+
+    GetLocalTime(&current_st);
+
+    for (i = 0; i < This->trigger_count; i++)
+    {
+        if (!(This->trigger[i].rgFlags & TASK_TRIGGER_FLAG_DISABLED))
+        {
+            get_begin_time(&This->trigger[i], &begin_ft);
+            get_end_time(&This->trigger[i], &end_ft);
+
+            switch (This->trigger[i].TriggerType)
+            {
+            case TASK_TIME_TRIGGER_ONCE:
+                st = current_st;
+                st.wHour = This->trigger[i].wStartHour;
+                st.wMinute = This->trigger[i].wStartMinute;
+                st.wSecond = 0;
+                st.wMilliseconds = 0;
+                SystemTimeToFileTime(&st, &current_ft);
+                if (CompareFileTime(&begin_ft, &current_ft) <= 0 && CompareFileTime(&current_ft, &end_ft) < 0)
+                {
+                    if (!have_best_time || CompareFileTime(&current_ft, &best_ft) < 0)
+                    {
+                        best_ft = current_ft;
+                        have_best_time = TRUE;
+                    }
+                }
+                break;
+
+            default:
+                FIXME("trigger type %u is not handled\n", This->trigger[i].TriggerType);
+                break;
+            }
+        }
+    }
+
+    if (have_best_time)
+    {
+        FileTimeToSystemTime(&best_ft, rt);
+        return S_OK;
+    }
+
+    memset(rt, 0, sizeof(*rt));
     return SCHED_S_TASK_NO_VALID_TRIGGERS;
 }
 
diff --git a/dlls/mstask/tests/task_trigger.c b/dlls/mstask/tests/task_trigger.c
index 9a20a5672c..e880ce4996 100644
--- a/dlls/mstask/tests/task_trigger.c
+++ b/dlls/mstask/tests/task_trigger.c
@@ -422,6 +422,53 @@ static void test_task_trigger(void)
     ok(ref == 0, "got %u\n", ref);
 }
 
+static void time_add_ms(SYSTEMTIME *st, DWORD ms)
+{
+    union
+    {
+        FILETIME ft;
+        ULONGLONG ll;
+    } ftll;
+    BOOL ret;
+
+    trace("old: %u/%u/%u wday %u %u:%02u:%02u.%03u\n",
+          st->wDay, st->wMonth, st->wYear, st->wDayOfWeek,
+          st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
+    ret = SystemTimeToFileTime(st, &ftll.ft);
+    ok(ret, "SystemTimeToFileTime error %u\n", GetLastError());
+
+    ftll.ll += ms * (ULONGLONG)10000;
+    ret = FileTimeToSystemTime(&ftll.ft, st);
+    ok(ret, "FileTimeToSystemTime error %u\n", GetLastError());
+    trace("new: %u/%u/%u wday %u %u:%02u:%02u.%03u\n",
+          st->wDay, st->wMonth, st->wYear, st->wDayOfWeek,
+          st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
+}
+
+static void trigger_add_ms(TASK_TRIGGER *data, DWORD ms, SYSTEMTIME *ret)
+{
+    SYSTEMTIME st;
+
+    st.wYear = data->wBeginYear;
+    st.wMonth = data->wBeginMonth;
+    st.wDayOfWeek = 0;
+    st.wDay = data->wBeginDay;
+    st.wHour = data->wStartHour;
+    st.wMinute = data->wStartMinute;
+    st.wSecond = 0;
+    st.wMilliseconds = 0;
+
+    time_add_ms(&st, ms);
+
+    data->wBeginYear = st.wYear;
+    data->wBeginMonth = st.wMonth;
+    data->wBeginDay = st.wDay;
+    data->wStartHour = st.wHour;
+    data->wStartMinute = st.wMinute;
+
+    *ret = st;
+}
+
 static void test_GetNextRunTime(void)
 {
     static const WCHAR task_name[] = { 'T','e','s','t','i','n','g',0 };
@@ -429,8 +476,9 @@ static void test_GetNextRunTime(void)
     HRESULT hr;
     ITask *task;
     ITaskTrigger *trigger;
+    TASK_TRIGGER data;
     WORD idx;
-    SYSTEMTIME st;
+    SYSTEMTIME st, cmp;
 
     hr = ITaskScheduler_NewWorkItem(test_task_scheduler, task_name, &CLSID_CTask,
                                     &IID_ITask, (IUnknown **)&task);
@@ -442,9 +490,9 @@ static void test_GetNextRunTime(void)
     memset(&st, 0xff, sizeof(st));
     hr = ITask_GetNextRunTime(task, &st);
     ok(hr == SCHED_S_TASK_NO_VALID_TRIGGERS, "got %#x\n", hr);
-    ok(!memcmp(&st, &st_empty, sizeof(st)), "got %d/%d/%d wday %d %d:%d:%d.%03d\n",
+    ok(!memcmp(&st, &st_empty, sizeof(st)), "got %u/%u/%u wday %u %u:%02u:%02u\n",
        st.wDay, st.wMonth, st.wYear, st.wDayOfWeek,
-       st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
+       st.wHour, st.wMinute, st.wSecond);
 
     hr = ITask_CreateTrigger(task, &idx, &trigger);
     ok(hr == S_OK, "got %#x\n", hr);
@@ -452,9 +500,32 @@ static void test_GetNextRunTime(void)
     memset(&st, 0xff, sizeof(st));
     hr = ITask_GetNextRunTime(task, &st);
     ok(hr == SCHED_S_TASK_NO_VALID_TRIGGERS, "got %#x\n", hr);
-    ok(!memcmp(&st, &st_empty, sizeof(st)), "got %d/%d/%d wday %d %d:%d:%d.%03d\n",
+    ok(!memcmp(&st, &st_empty, sizeof(st)), "got %u/%u/%u wday %u %u:%02u:%02u\n",
        st.wDay, st.wMonth, st.wYear, st.wDayOfWeek,
-       st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
+       st.wHour, st.wMinute, st.wSecond);
+
+    /* TASK_TIME_TRIGGER_ONCE */
+
+    hr = ITaskTrigger_GetTrigger(trigger, &data);
+    ok(hr == S_OK, "got %#x\n", hr);
+    data.rgFlags &= ~TASK_TRIGGER_FLAG_DISABLED;
+    data.TriggerType = TASK_TIME_TRIGGER_ONCE;
+    /* add 5 minutes to avoid races */
+    trigger_add_ms(&data, 5 * 60 * 1000, &cmp);
+    hr = ITaskTrigger_SetTrigger(trigger, &data);
+    ok(hr == S_OK, "got %#x\n", hr);
+
+    memset(&st, 0xff, sizeof(st));
+    hr = ITask_GetNextRunTime(task, &st);
+    ok(hr == S_OK, "got %#x\n", hr);
+    ok(!memcmp(&st, &cmp, sizeof(st)), "got %u/%u/%u wday %u %u:%02u:%02u\n",
+       st.wDay, st.wMonth, st.wYear, st.wDayOfWeek,
+       st.wHour, st.wMinute, st.wSecond);
+
+    /* FIXME: TASK_TIME_TRIGGER_DAILY */
+    /* FIXME: TASK_TIME_TRIGGER_WEEKLY */
+    /* FIXME: TASK_TIME_TRIGGER_MONTHLYDATE */
+    /* FIXME: TASK_TIME_TRIGGER_MONTHLYDOW */
 
     ITaskTrigger_Release(trigger);
     ITask_Release(task);
-- 
2.16.3




More information about the wine-devel mailing list