[SCHEDSVC] Fix the job start time calculation for given days of week.
[reactos.git] / base / services / schedsvc / job.c
index e1a8f01..2f24b95 100644 (file)
@@ -449,81 +449,102 @@ done:
 }
 
 
-static
-WORD
-DaysOfMonth(
-    WORD wMonth,
-    WORD wYear)
-{
-    WORD wDaysArray[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-    if (wMonth == 2 && wYear % 4 == 0 && wYear % 400 != 0)
-        return 29;
-
-    return wDaysArray[wMonth];
-}
-
-
 VOID
 CalculateNextStartTime(
     _In_ PJOB pJob)
 {
-    SYSTEMTIME StartTime;
-    FILETIME FileTime;
-    DWORD_PTR Now;
+    SYSTEMTIME CurrentSystemTime, StartSystemTime;
+    FILETIME StartFileTime;
+    WORD wDaysOffset, wTempOffset, i, wJobDayOfWeek;
+    DWORD_PTR CurrentTimeMs;
+    BOOL bDaysOffsetValid;
 
     TRACE("CalculateNextStartTime(%p)\n", pJob);
+    TRACE("JobTime: %lu\n", pJob->JobTime);
+    TRACE("DaysOfWeek: 0x%x\n", pJob->DaysOfWeek);
+    TRACE("DaysOfMonth: 0x%x\n", pJob->DaysOfMonth);
 
-    GetLocalTime(&StartTime);
+    GetLocalTime(&CurrentSystemTime);
 
-    Now = (DWORD_PTR)StartTime.wHour * 3600000 +
-          (DWORD_PTR)StartTime.wMinute * 60000;
+    CurrentTimeMs = (DWORD_PTR)CurrentSystemTime.wHour * 3600000 +
+                    (DWORD_PTR)CurrentSystemTime.wMinute * 60000;
 
-    StartTime.wMilliseconds = 0;
-    StartTime.wSecond = 0;
-    StartTime.wHour = (WORD)(pJob->JobTime / 3600000);
-    StartTime.wMinute = (WORD)((pJob->JobTime % 3600000) / 60000);
+    CopyMemory(&StartSystemTime, &CurrentSystemTime, sizeof(SYSTEMTIME));
 
-    if (pJob->DaysOfMonth != 0)
-    {
-         FIXME("Support DaysOfMonth!\n");
-    }
-    else if (pJob->DaysOfWeek != 0)
+    StartSystemTime.wMilliseconds = 0;
+    StartSystemTime.wSecond = 0;
+    StartSystemTime.wHour = (WORD)(pJob->JobTime / 3600000);
+    StartSystemTime.wMinute = (WORD)((pJob->JobTime % 3600000) / 60000);
+
+    bDaysOffsetValid = FALSE;
+    wDaysOffset = 0;
+    if ((pJob->DaysOfWeek == 0) && (pJob->DaysOfMonth == 0))
     {
-         FIXME("Support DaysOfWeek!\n");
+        if (CurrentTimeMs >= pJob->JobTime)
+        {
+            TRACE("Tomorrow!\n");
+            wDaysOffset = 1;
+        }
+
+        bDaysOffsetValid = TRUE;
     }
     else
     {
-        /* Start the job tomorrow */
-        if (Now > pJob->JobTime)
+        if (pJob->DaysOfWeek != 0)
         {
-            if (StartTime.wDay + 1 > DaysOfMonth(StartTime.wMonth, StartTime.wYear))
+            TRACE("DaysOfWeek!\n");
+            for (i = 0; i < 7; i++)
             {
-                if (StartTime.wMonth == 12)
-                {
-                    StartTime.wDay = 1;
-                    StartTime.wMonth = 1;
-                    StartTime.wYear++;
-                }
-                else
+                if (pJob->DaysOfWeek & (1 << i))
                 {
-                    StartTime.wDay = 1;
-                    StartTime.wMonth++;
+                    /* Adjust the ranges */
+                    wJobDayOfWeek = (i + 1) % 7;
+                    TRACE("wJobDayOfWeek: %hu\n", wJobDayOfWeek);
+                    TRACE("CurrentSystemTime.wDayOfWeek: %hu\n", CurrentSystemTime.wDayOfWeek);
+
+                    /* Calculate the days offset */
+                    if ((CurrentSystemTime.wDayOfWeek > wJobDayOfWeek ) ||
+                        ((CurrentSystemTime.wDayOfWeek == wJobDayOfWeek) && (CurrentTimeMs >= pJob->JobTime)))
+                    {
+                        wTempOffset = 7 - CurrentSystemTime.wDayOfWeek + wJobDayOfWeek;
+                        TRACE("wTempOffset: %hu\n", wTempOffset);
+                    }
+                    else
+                    {
+                        wTempOffset = wJobDayOfWeek - CurrentSystemTime.wDayOfWeek;
+                        TRACE("wTempOffset: %hu\n", wTempOffset);
+                    }
+
+                    /* Use the smallest offset */
+                    if (bDaysOffsetValid == FALSE)
+                    {
+                        wDaysOffset = wTempOffset;
+                        bDaysOffsetValid = TRUE;
+                    }
+                    else
+                    {
+                        if (wTempOffset < wDaysOffset)
+                            wDaysOffset = wTempOffset;
+                    }
                 }
             }
-            else
-            {
-                StartTime.wDay++;
-            }
+        }
+
+        if (pJob->DaysOfMonth != 0)
+        {
+            FIXME("Support DaysOfMonth!\n");
         }
     }
 
-    TRACE("Next start: %02hu:%02hu %02hu.%02hu.%hu\n", StartTime.wHour,
-          StartTime.wMinute, StartTime.wDay, StartTime.wMonth, StartTime.wYear);
+    TRACE("wDaysOffset: %hu\n", wDaysOffset);
 
-    SystemTimeToFileTime(&StartTime, &FileTime);
-    pJob->StartTime.u.LowPart = FileTime.dwLowDateTime;
-    pJob->StartTime.u.HighPart = FileTime.dwHighDateTime;
+    SystemTimeToFileTime(&StartSystemTime, &StartFileTime);
+    pJob->StartTime.u.LowPart = StartFileTime.dwLowDateTime;
+    pJob->StartTime.u.HighPart = StartFileTime.dwHighDateTime;
+    if (bDaysOffsetValid && wDaysOffset != 0)
+    {
+        pJob->StartTime.QuadPart += ((ULONGLONG)wDaysOffset * 24 * 60 * 60 * 10000);
+    }
 }