[SCHEDSVC]
[reactos.git] / reactos / base / services / schedsvc / rpcserver.c
index 6797ce1..1ca2b35 100644 (file)
@@ -21,7 +21,7 @@
  * PROJECT:          ReactOS Services
  * FILE:             base/services/schedsvc/rpcserver.c
  * PURPOSE:          Scheduler service
- * PROGRAMMER:       Eric Kohl
+ * PROGRAMMER:       Eric Kohl <eric.kohl@reactos.org>
  */
 
 /* INCLUDES *****************************************************************/
@@ -32,6 +32,7 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(schedsvc);
 
+
 /* FUNCTIONS *****************************************************************/
 
 DWORD
@@ -85,6 +86,57 @@ NetrJobAdd(
     LPAT_INFO pAtInfo,
     LPDWORD pJobId)
 {
+    PJOB pJob;
+
+    TRACE("NetrJobAdd(%S %p %p)\n",
+          ServerName, pAtInfo, pJobId);
+
+    /* Allocate a new job object */
+    pJob = HeapAlloc(GetProcessHeap(),
+                     HEAP_ZERO_MEMORY,
+                     sizeof(JOB) + wcslen(pAtInfo->Command) * sizeof(WCHAR));
+    if (pJob == NULL)
+        return ERROR_OUTOFMEMORY;
+
+    /* Initialize the job object */
+    pJob->JobTime = pAtInfo->JobTime;
+    pJob->DaysOfMonth = pAtInfo->DaysOfMonth;
+    pJob->DaysOfWeek = pAtInfo->DaysOfWeek;
+    pJob->Flags = pAtInfo->Flags;
+    wcscpy(pJob->Command, pAtInfo->Command);
+
+    /* Acquire the job list lock exclusively */
+    RtlAcquireResourceExclusive(&JobListLock, TRUE);
+
+    /* Assign a new job ID */
+    pJob->JobId = dwNextJobId++;
+    dwJobCount++;
+
+    // Cancel the start timer
+
+    /* Append the new job to the job list */
+    InsertTailList(&JobListHead, &pJob->JobEntry);
+
+    /* Save the job in the registry */
+    SaveJob(pJob);
+
+    /* Calculate the next start time */
+    CalculateNextStartTime(pJob);
+
+    /* Insert the job into the start list */
+    InsertJobIntoStartList(&StartListHead, pJob);
+#if 0
+    DumpStartList(&StartListHead);
+#endif
+
+    // Update the start timer
+
+    /* Release the job list lock */
+    RtlReleaseResource(&JobListLock);
+
+    /* Return the new job ID */
+    *pJobId = pJob->JobId;
+
     return ERROR_SUCCESS;
 }
 
@@ -97,6 +149,55 @@ NetrJobDel(
     DWORD MinJobId,
     DWORD MaxJobId)
 {
+    PLIST_ENTRY JobEntry, NextEntry;
+    PJOB CurrentJob;
+
+    TRACE("NetrJobDel(%S %lu %lu)\n",
+          ServerName, MinJobId, MaxJobId);
+
+    /* Check the job IDs */
+    if (MinJobId > MaxJobId)
+        return ERROR_INVALID_PARAMETER;
+
+    /* Acquire the job list lock exclusively */
+    RtlAcquireResourceExclusive(&JobListLock, TRUE);
+
+    // Cancel the start timer
+
+    JobEntry = JobListHead.Flink;
+    while (JobEntry != &JobListHead)
+    {
+        CurrentJob = CONTAINING_RECORD(JobEntry, JOB, JobEntry);
+
+        if ((CurrentJob->JobId >= MinJobId) && (CurrentJob->JobId <= MaxJobId))
+        {
+            /* Remove the job from the start list */
+            RemoveEntryList(&CurrentJob->StartEntry);
+#if 0
+            DumpStartList(&StartListHead);
+#endif
+
+            /* Remove the job from the registry */
+            DeleteJob(CurrentJob);
+
+            NextEntry = JobEntry->Flink;
+            if (RemoveEntryList(JobEntry))
+            {
+                dwJobCount--;
+                HeapFree(GetProcessHeap(), 0, CurrentJob);
+                JobEntry = NextEntry;
+                continue;
+            }
+        }
+
+        JobEntry = JobEntry->Flink;
+    }
+
+    // Update the start timer
+
+    /* Release the job list lock */
+    RtlReleaseResource(&JobListLock);
+
     return ERROR_SUCCESS;
 }
 
@@ -111,7 +212,124 @@ NetrJobEnum(
     LPDWORD pTotalEntries,
     LPDWORD pResumeHandle)
 {
-    return ERROR_SUCCESS;
+    PLIST_ENTRY JobEntry;
+    PJOB CurrentJob;
+    PAT_ENUM pEnum;
+    DWORD dwStartIndex, dwIndex;
+    DWORD dwEntriesToRead, dwEntriesRead;
+    DWORD dwRequiredSize, dwEntrySize;
+    PWSTR pString;
+    DWORD dwError = ERROR_SUCCESS;
+
+    TRACE("NetrJobEnum(%S %p %lu %p %p)\n",
+          ServerName, pEnumContainer, PreferedMaximumLength, pTotalEntries, pResumeHandle);
+
+    if (pEnumContainer == NULL)
+    {
+        *pTotalEntries = 0;
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    if (*pResumeHandle >= dwJobCount)
+    {
+        *pTotalEntries = 0;
+        return ERROR_SUCCESS;
+    }
+
+    dwStartIndex = *pResumeHandle;
+    TRACE("dwStartIndex: %lu\n", dwStartIndex);
+
+    /* Acquire the job list lock exclusively */
+    RtlAcquireResourceShared(&JobListLock, TRUE);
+
+    dwEntriesToRead = 0;
+    dwRequiredSize = 0;
+    dwIndex = 0;
+    JobEntry = JobListHead.Flink;
+    while (JobEntry != &JobListHead)
+    {
+        CurrentJob = CONTAINING_RECORD(JobEntry, JOB, JobEntry);
+
+        if (dwIndex >= dwStartIndex)
+        {
+            TRACE("dwIndex: %lu\n", dwIndex);
+            dwEntrySize = sizeof(AT_ENUM) +
+                          (wcslen(CurrentJob->Command) + 1) * sizeof(WCHAR);
+            TRACE("dwEntrySize: %lu\n", dwEntrySize);
+
+            if ((PreferedMaximumLength != ULONG_MAX) &&
+                (dwRequiredSize + dwEntrySize > PreferedMaximumLength))
+                break;
+
+            dwRequiredSize += dwEntrySize;
+            dwEntriesToRead++;
+        }
+
+        JobEntry = JobEntry->Flink;
+        dwIndex++;
+    }
+    TRACE("dwEntriesToRead: %lu\n", dwEntriesToRead);
+    TRACE("dwRequiredSize: %lu\n", dwRequiredSize);
+
+    if (PreferedMaximumLength != ULONG_MAX)
+        dwRequiredSize = PreferedMaximumLength;
+
+    TRACE("Allocating dwRequiredSize: %lu\n", dwRequiredSize);
+    pEnum = midl_user_allocate(dwRequiredSize);
+    if (pEnum == NULL)
+    {
+        dwError = ERROR_OUTOFMEMORY;
+        goto done;
+    }
+
+    pString = (PWSTR)((ULONG_PTR)pEnum + dwEntriesToRead * sizeof(AT_ENUM));
+
+    dwEntriesRead = 0;
+    dwIndex = 0;
+    JobEntry = JobListHead.Flink;
+    while (JobEntry != &JobListHead)
+    {
+        CurrentJob = CONTAINING_RECORD(JobEntry, JOB, JobEntry);
+
+        if (dwIndex >= dwStartIndex)
+        {
+            pEnum[dwIndex].JobId = CurrentJob->JobId;
+            pEnum[dwIndex].JobTime = CurrentJob->JobTime;
+            pEnum[dwIndex].DaysOfMonth = CurrentJob->DaysOfMonth;
+            pEnum[dwIndex].DaysOfWeek = CurrentJob->DaysOfWeek;
+            pEnum[dwIndex].Flags = CurrentJob->Flags;
+            pEnum[dwIndex].Command = pString;
+            wcscpy(pString, CurrentJob->Command);
+
+            pString = (PWSTR)((ULONG_PTR)pString + (wcslen(CurrentJob->Command) + 1) * sizeof(WCHAR));
+
+            dwEntriesRead++;
+        }
+
+        if (dwEntriesRead == dwEntriesToRead)
+            break;
+
+        /* Next job */
+        JobEntry = JobEntry->Flink;
+        dwIndex++;
+    }
+
+    pEnumContainer->EntriesRead = dwEntriesRead;
+    pEnumContainer->Buffer = pEnum;
+
+    *pTotalEntries = dwJobCount;
+    *pResumeHandle = dwIndex;
+
+    if (dwEntriesRead + dwStartIndex < dwJobCount)
+        dwError = ERROR_MORE_DATA;
+    else
+        dwError = ERROR_SUCCESS;
+
+done:
+    /* Release the job list lock */
+    RtlReleaseResource(&JobListLock);
+
+    return dwError;
 }
 
 
@@ -123,7 +341,62 @@ NetrJobGetInfo(
     DWORD JobId,
     LPAT_INFO *ppAtInfo)
 {
-    return ERROR_SUCCESS;
+    PLIST_ENTRY JobEntry;
+    PJOB CurrentJob;
+    PAT_INFO pInfo;
+    DWORD dwError = ERROR_FILE_NOT_FOUND;
+
+    TRACE("NetrJobGetInfo(%S %lu %p)\n",
+          ServerName, JobId, ppAtInfo);
+
+    /* Acquire the job list lock exclusively */
+    RtlAcquireResourceShared(&JobListLock, TRUE);
+
+    /* Traverse the job list */
+    JobEntry = JobListHead.Flink;
+    while (JobEntry != &JobListHead)
+    {
+        CurrentJob = CONTAINING_RECORD(JobEntry, JOB, JobEntry);
+
+        /* Do we have the right job? */
+        if (CurrentJob->JobId == JobId)
+        {
+            pInfo = midl_user_allocate(sizeof(AT_INFO));
+            if (pInfo == NULL)
+            {
+                dwError = ERROR_OUTOFMEMORY;
+                goto done;
+            }
+
+            pInfo->Command = midl_user_allocate((wcslen(CurrentJob->Command) + 1) * sizeof(WCHAR));
+            if (pInfo->Command == NULL)
+            {
+                midl_user_free(pInfo);
+                dwError = ERROR_OUTOFMEMORY;
+                goto done;
+            }
+
+            pInfo->JobTime = CurrentJob->JobTime;
+            pInfo->DaysOfMonth = CurrentJob->DaysOfMonth;
+            pInfo->DaysOfWeek = CurrentJob->DaysOfWeek;
+            pInfo->Flags = CurrentJob->Flags;
+            wcscpy(pInfo->Command, CurrentJob->Command);
+
+            *ppAtInfo = pInfo;
+
+            dwError = ERROR_SUCCESS;
+            goto done;
+        }
+
+        /* Next job */
+        JobEntry = JobEntry->Flink;
+    }
+
+done:
+    /* Release the job list lock */
+    RtlReleaseResource(&JobListLock);
+
+    return dwError;
 }
 
 /* EOF */