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 start time
126 // Insert job into start list
128 // Update start timer
130 /* Return the new job ID */
131 *pJobId
= pJob
->JobId
;
133 return ERROR_SUCCESS
;
141 ATSVC_HANDLE ServerName
,
145 PLIST_ENTRY JobEntry
, NextEntry
;
148 TRACE("NetrJobDel(%S %lu %lu)\n",
149 ServerName
, MinJobId
, MaxJobId
);
151 /* Check the job IDs */
152 if (MinJobId
> MaxJobId
)
153 return ERROR_INVALID_PARAMETER
;
155 /* Acquire the job list lock exclusively */
156 RtlAcquireResourceExclusive(&JobListLock
, TRUE
);
158 JobEntry
= JobListHead
.Flink
;
159 while (JobEntry
!= &JobListHead
)
161 CurrentJob
= CONTAINING_RECORD(JobEntry
, JOB
, JobEntry
);
163 if ((CurrentJob
->JobId
>= MinJobId
) && (CurrentJob
->JobId
<= MaxJobId
))
165 // Remove job from start list
167 // Update start timer
169 /* Remove the job from the registry */
170 DeleteJob(CurrentJob
);
172 NextEntry
= JobEntry
->Flink
;
173 if (RemoveEntryList(JobEntry
))
176 HeapFree(GetProcessHeap(), 0, CurrentJob
);
177 JobEntry
= NextEntry
;
182 JobEntry
= JobEntry
->Flink
;
185 /* Release the job list lock */
186 RtlReleaseResource(&JobListLock
);
188 return ERROR_SUCCESS
;
196 ATSVC_HANDLE ServerName
,
197 LPAT_ENUM_CONTAINER pEnumContainer
,
198 DWORD PreferedMaximumLength
,
199 LPDWORD pTotalEntries
,
200 LPDWORD pResumeHandle
)
202 PLIST_ENTRY JobEntry
;
205 DWORD dwStartIndex
, dwIndex
;
206 DWORD dwEntriesToRead
, dwEntriesRead
;
207 DWORD dwRequiredSize
, dwEntrySize
;
209 DWORD dwError
= ERROR_SUCCESS
;
211 TRACE("NetrJobEnum(%S %p %lu %p %p)\n",
212 ServerName
, pEnumContainer
, PreferedMaximumLength
, pTotalEntries
, pResumeHandle
);
214 if (pEnumContainer
== NULL
)
217 return ERROR_INVALID_PARAMETER
;
220 if (*pResumeHandle
>= dwJobCount
)
223 return ERROR_SUCCESS
;
226 dwStartIndex
= *pResumeHandle
;
227 TRACE("dwStartIndex: %lu\n", dwStartIndex
);
229 /* Acquire the job list lock exclusively */
230 RtlAcquireResourceShared(&JobListLock
, TRUE
);
235 JobEntry
= JobListHead
.Flink
;
236 while (JobEntry
!= &JobListHead
)
238 CurrentJob
= CONTAINING_RECORD(JobEntry
, JOB
, JobEntry
);
240 if (dwIndex
>= dwStartIndex
)
242 TRACE("dwIndex: %lu\n", dwIndex
);
243 dwEntrySize
= sizeof(AT_ENUM
) +
244 (wcslen(CurrentJob
->Command
) + 1) * sizeof(WCHAR
);
245 TRACE("dwEntrySize: %lu\n", dwEntrySize
);
247 if ((PreferedMaximumLength
!= DWORD_MAX
) &&
248 (dwRequiredSize
+ dwEntrySize
> PreferedMaximumLength
))
251 dwRequiredSize
+= dwEntrySize
;
255 JobEntry
= JobEntry
->Flink
;
258 TRACE("dwEntriesToRead: %lu\n", dwEntriesToRead
);
259 TRACE("dwRequiredSize: %lu\n", dwRequiredSize
);
261 if (PreferedMaximumLength
!= DWORD_MAX
)
262 dwRequiredSize
= PreferedMaximumLength
;
264 TRACE("Allocating dwRequiredSize: %lu\n", dwRequiredSize
);
265 pEnum
= midl_user_allocate(dwRequiredSize
);
268 dwError
= ERROR_OUTOFMEMORY
;
272 pString
= (PWSTR
)((ULONG_PTR
)pEnum
+ dwEntriesToRead
* sizeof(AT_ENUM
));
276 JobEntry
= JobListHead
.Flink
;
277 while (JobEntry
!= &JobListHead
)
279 CurrentJob
= CONTAINING_RECORD(JobEntry
, JOB
, JobEntry
);
281 if (dwIndex
>= dwStartIndex
)
283 pEnum
[dwIndex
].JobId
= CurrentJob
->JobId
;
284 pEnum
[dwIndex
].JobTime
= CurrentJob
->JobTime
;
285 pEnum
[dwIndex
].DaysOfMonth
= CurrentJob
->DaysOfMonth
;
286 pEnum
[dwIndex
].DaysOfWeek
= CurrentJob
->DaysOfWeek
;
287 pEnum
[dwIndex
].Flags
= CurrentJob
->Flags
;
288 pEnum
[dwIndex
].Command
= pString
;
289 wcscpy(pString
, CurrentJob
->Command
);
291 pString
= (PWSTR
)((ULONG_PTR
)pString
+ (wcslen(CurrentJob
->Command
) + 1) * sizeof(WCHAR
));
296 if (dwEntriesRead
== dwEntriesToRead
)
300 JobEntry
= JobEntry
->Flink
;
304 pEnumContainer
->EntriesRead
= dwEntriesRead
;
305 pEnumContainer
->Buffer
= pEnum
;
307 *pTotalEntries
= dwJobCount
;
308 *pResumeHandle
= dwIndex
;
310 if (dwEntriesRead
+ dwStartIndex
< dwJobCount
)
311 dwError
= ERROR_MORE_DATA
;
313 dwError
= ERROR_SUCCESS
;
316 /* Release the job list lock */
317 RtlReleaseResource(&JobListLock
);
327 ATSVC_HANDLE ServerName
,
331 PLIST_ENTRY JobEntry
;
334 DWORD dwError
= ERROR_FILE_NOT_FOUND
;
336 TRACE("NetrJobGetInfo(%S %lu %p)\n",
337 ServerName
, JobId
, ppAtInfo
);
339 /* Acquire the job list lock exclusively */
340 RtlAcquireResourceShared(&JobListLock
, TRUE
);
342 /* Traverse the job list */
343 JobEntry
= JobListHead
.Flink
;
344 while (JobEntry
!= &JobListHead
)
346 CurrentJob
= CONTAINING_RECORD(JobEntry
, JOB
, JobEntry
);
348 /* Do we have the right job? */
349 if (CurrentJob
->JobId
== JobId
)
351 pInfo
= midl_user_allocate(sizeof(AT_INFO
));
354 dwError
= ERROR_OUTOFMEMORY
;
358 pInfo
->Command
= midl_user_allocate((wcslen(CurrentJob
->Command
) + 1) * sizeof(WCHAR
));
359 if (pInfo
->Command
== NULL
)
361 midl_user_free(pInfo
);
362 dwError
= ERROR_OUTOFMEMORY
;
366 pInfo
->JobTime
= CurrentJob
->JobTime
;
367 pInfo
->DaysOfMonth
= CurrentJob
->DaysOfMonth
;
368 pInfo
->DaysOfWeek
= CurrentJob
->DaysOfWeek
;
369 pInfo
->Flags
= CurrentJob
->Flags
;
370 wcscpy(pInfo
->Command
, CurrentJob
->Command
);
374 dwError
= ERROR_SUCCESS
;
379 JobEntry
= JobEntry
->Flink
;
383 /* Release the job list lock */
384 RtlReleaseResource(&JobListLock
);