3 * Copyright (C) 2015 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS Services
22 * FILE: base/services/schedsvc/rpcserver.c
23 * PURPOSE: Scheduler service
24 * PROGRAMMER: Eric Kohl <eric.kohl@reactos.org>
27 /* INCLUDES *****************************************************************/
33 WINE_DEFAULT_DEBUG_CHANNEL(schedsvc
);
36 /* FUNCTIONS *****************************************************************/
45 Status
= RpcServerUseProtseqEpW(L
"ncacn_np", 20, L
"\\pipe\\atsvc", NULL
);
46 if (Status
!= RPC_S_OK
)
48 ERR("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
52 Status
= RpcServerRegisterIf(atsvc_v1_0_s_ifspec
, NULL
, NULL
);
53 if (Status
!= RPC_S_OK
)
55 ERR("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
59 Status
= RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT
, FALSE
);
60 if (Status
!= RPC_S_OK
)
62 ERR("RpcServerListen() failed (Status %lx)\n", Status
);
69 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
71 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
75 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
77 HeapFree(GetProcessHeap(), 0, ptr
);
85 ATSVC_HANDLE ServerName
,
91 TRACE("NetrJobAdd(%S %p %p)\n",
92 ServerName
, pAtInfo
, pJobId
);
94 /* Allocate a new job object */
95 pJob
= HeapAlloc(GetProcessHeap(),
97 sizeof(JOB
) + wcslen(pAtInfo
->Command
) * sizeof(WCHAR
));
99 return ERROR_OUTOFMEMORY
;
101 /* Initialize the job object */
102 pJob
->JobTime
= pAtInfo
->JobTime
;
103 pJob
->DaysOfMonth
= pAtInfo
->DaysOfMonth
;
104 pJob
->DaysOfWeek
= pAtInfo
->DaysOfWeek
;
105 pJob
->Flags
= pAtInfo
->Flags
;
106 wcscpy(pJob
->Command
, pAtInfo
->Command
);
108 /* Acquire the job list lock exclusively */
109 RtlAcquireResourceExclusive(&JobListLock
, TRUE
);
111 /* Assign a new job ID */
112 pJob
->JobId
= dwNextJobId
++;
115 /* Append the new job to the job list */
116 InsertTailList(&JobListHead
, &pJob
->JobEntry
);
118 /* Release the job list lock */
119 RtlReleaseResource(&JobListLock
);
121 /* Save the job in the registry */
124 /* Calculate the next start time */
125 CalculateNextStartTime(pJob
);
127 // Insert job into the start list
129 // Update the start timer
131 /* Return the new job ID */
132 *pJobId
= pJob
->JobId
;
134 return ERROR_SUCCESS
;
142 ATSVC_HANDLE ServerName
,
146 PLIST_ENTRY JobEntry
, NextEntry
;
149 TRACE("NetrJobDel(%S %lu %lu)\n",
150 ServerName
, MinJobId
, MaxJobId
);
152 /* Check the job IDs */
153 if (MinJobId
> MaxJobId
)
154 return ERROR_INVALID_PARAMETER
;
156 /* Acquire the job list lock exclusively */
157 RtlAcquireResourceExclusive(&JobListLock
, TRUE
);
159 JobEntry
= JobListHead
.Flink
;
160 while (JobEntry
!= &JobListHead
)
162 CurrentJob
= CONTAINING_RECORD(JobEntry
, JOB
, JobEntry
);
164 if ((CurrentJob
->JobId
>= MinJobId
) && (CurrentJob
->JobId
<= MaxJobId
))
166 // Remove job from the start list
168 // Update the start timer
170 /* Remove the job from the registry */
171 DeleteJob(CurrentJob
);
173 NextEntry
= JobEntry
->Flink
;
174 if (RemoveEntryList(JobEntry
))
177 HeapFree(GetProcessHeap(), 0, CurrentJob
);
178 JobEntry
= NextEntry
;
183 JobEntry
= JobEntry
->Flink
;
186 /* Release the job list lock */
187 RtlReleaseResource(&JobListLock
);
189 return ERROR_SUCCESS
;
197 ATSVC_HANDLE ServerName
,
198 LPAT_ENUM_CONTAINER pEnumContainer
,
199 DWORD PreferedMaximumLength
,
200 LPDWORD pTotalEntries
,
201 LPDWORD pResumeHandle
)
203 PLIST_ENTRY JobEntry
;
206 DWORD dwStartIndex
, dwIndex
;
207 DWORD dwEntriesToRead
, dwEntriesRead
;
208 DWORD dwRequiredSize
, dwEntrySize
;
210 DWORD dwError
= ERROR_SUCCESS
;
212 TRACE("NetrJobEnum(%S %p %lu %p %p)\n",
213 ServerName
, pEnumContainer
, PreferedMaximumLength
, pTotalEntries
, pResumeHandle
);
215 if (pEnumContainer
== NULL
)
218 return ERROR_INVALID_PARAMETER
;
221 if (*pResumeHandle
>= dwJobCount
)
224 return ERROR_SUCCESS
;
227 dwStartIndex
= *pResumeHandle
;
228 TRACE("dwStartIndex: %lu\n", dwStartIndex
);
230 /* Acquire the job list lock exclusively */
231 RtlAcquireResourceShared(&JobListLock
, TRUE
);
236 JobEntry
= JobListHead
.Flink
;
237 while (JobEntry
!= &JobListHead
)
239 CurrentJob
= CONTAINING_RECORD(JobEntry
, JOB
, JobEntry
);
241 if (dwIndex
>= dwStartIndex
)
243 TRACE("dwIndex: %lu\n", dwIndex
);
244 dwEntrySize
= sizeof(AT_ENUM
) +
245 (wcslen(CurrentJob
->Command
) + 1) * sizeof(WCHAR
);
246 TRACE("dwEntrySize: %lu\n", dwEntrySize
);
248 if ((PreferedMaximumLength
!= DWORD_MAX
) &&
249 (dwRequiredSize
+ dwEntrySize
> PreferedMaximumLength
))
252 dwRequiredSize
+= dwEntrySize
;
256 JobEntry
= JobEntry
->Flink
;
259 TRACE("dwEntriesToRead: %lu\n", dwEntriesToRead
);
260 TRACE("dwRequiredSize: %lu\n", dwRequiredSize
);
262 if (PreferedMaximumLength
!= DWORD_MAX
)
263 dwRequiredSize
= PreferedMaximumLength
;
265 TRACE("Allocating dwRequiredSize: %lu\n", dwRequiredSize
);
266 pEnum
= midl_user_allocate(dwRequiredSize
);
269 dwError
= ERROR_OUTOFMEMORY
;
273 pString
= (PWSTR
)((ULONG_PTR
)pEnum
+ dwEntriesToRead
* sizeof(AT_ENUM
));
277 JobEntry
= JobListHead
.Flink
;
278 while (JobEntry
!= &JobListHead
)
280 CurrentJob
= CONTAINING_RECORD(JobEntry
, JOB
, JobEntry
);
282 if (dwIndex
>= dwStartIndex
)
284 pEnum
[dwIndex
].JobId
= CurrentJob
->JobId
;
285 pEnum
[dwIndex
].JobTime
= CurrentJob
->JobTime
;
286 pEnum
[dwIndex
].DaysOfMonth
= CurrentJob
->DaysOfMonth
;
287 pEnum
[dwIndex
].DaysOfWeek
= CurrentJob
->DaysOfWeek
;
288 pEnum
[dwIndex
].Flags
= CurrentJob
->Flags
;
289 pEnum
[dwIndex
].Command
= pString
;
290 wcscpy(pString
, CurrentJob
->Command
);
292 pString
= (PWSTR
)((ULONG_PTR
)pString
+ (wcslen(CurrentJob
->Command
) + 1) * sizeof(WCHAR
));
297 if (dwEntriesRead
== dwEntriesToRead
)
301 JobEntry
= JobEntry
->Flink
;
305 pEnumContainer
->EntriesRead
= dwEntriesRead
;
306 pEnumContainer
->Buffer
= pEnum
;
308 *pTotalEntries
= dwJobCount
;
309 *pResumeHandle
= dwIndex
;
311 if (dwEntriesRead
+ dwStartIndex
< dwJobCount
)
312 dwError
= ERROR_MORE_DATA
;
314 dwError
= ERROR_SUCCESS
;
317 /* Release the job list lock */
318 RtlReleaseResource(&JobListLock
);
328 ATSVC_HANDLE ServerName
,
332 PLIST_ENTRY JobEntry
;
335 DWORD dwError
= ERROR_FILE_NOT_FOUND
;
337 TRACE("NetrJobGetInfo(%S %lu %p)\n",
338 ServerName
, JobId
, ppAtInfo
);
340 /* Acquire the job list lock exclusively */
341 RtlAcquireResourceShared(&JobListLock
, TRUE
);
343 /* Traverse the job list */
344 JobEntry
= JobListHead
.Flink
;
345 while (JobEntry
!= &JobListHead
)
347 CurrentJob
= CONTAINING_RECORD(JobEntry
, JOB
, JobEntry
);
349 /* Do we have the right job? */
350 if (CurrentJob
->JobId
== JobId
)
352 pInfo
= midl_user_allocate(sizeof(AT_INFO
));
355 dwError
= ERROR_OUTOFMEMORY
;
359 pInfo
->Command
= midl_user_allocate((wcslen(CurrentJob
->Command
) + 1) * sizeof(WCHAR
));
360 if (pInfo
->Command
== NULL
)
362 midl_user_free(pInfo
);
363 dwError
= ERROR_OUTOFMEMORY
;
367 pInfo
->JobTime
= CurrentJob
->JobTime
;
368 pInfo
->DaysOfMonth
= CurrentJob
->DaysOfMonth
;
369 pInfo
->DaysOfWeek
= CurrentJob
->DaysOfWeek
;
370 pInfo
->Flags
= CurrentJob
->Flags
;
371 wcscpy(pInfo
->Command
, CurrentJob
->Command
);
375 dwError
= ERROR_SUCCESS
;
380 JobEntry
= JobEntry
->Flink
;
384 /* Release the job list lock */
385 RtlReleaseResource(&JobListLock
);