oleaut32: Remove unnecessary consts.
[wine.git] / dlls / mstask / task_scheduler.c
blob7998b3a50e645ddf424c61b3e63f1f65dce6bac6
1 /*
2 * Copyright (C) 2008 Google (Roy Shea)
3 * Copyright (C) 2018 Dmitry Timoshkov
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library 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 GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <stdarg.h>
22 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "initguid.h"
27 #include "objbase.h"
28 #include "taskschd.h"
29 #include "mstask.h"
30 #include "mstask_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(mstask);
35 typedef struct
37 ITaskScheduler ITaskScheduler_iface;
38 LONG ref;
39 ITaskService *service;
40 } TaskSchedulerImpl;
42 typedef struct
44 IEnumWorkItems IEnumWorkItems_iface;
45 LONG ref;
46 HANDLE handle;
47 } EnumWorkItemsImpl;
49 static inline TaskSchedulerImpl *impl_from_ITaskScheduler(ITaskScheduler *iface)
51 return CONTAINING_RECORD(iface, TaskSchedulerImpl, ITaskScheduler_iface);
54 static inline EnumWorkItemsImpl *impl_from_IEnumWorkItems(IEnumWorkItems *iface)
56 return CONTAINING_RECORD(iface, EnumWorkItemsImpl, IEnumWorkItems_iface);
59 static void TaskSchedulerDestructor(TaskSchedulerImpl *This)
61 TRACE("%p\n", This);
62 ITaskService_Release(This->service);
63 heap_free(This);
64 InterlockedDecrement(&dll_ref);
67 static HRESULT WINAPI EnumWorkItems_QueryInterface(IEnumWorkItems *iface, REFIID riid, void **obj)
69 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface);
71 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
73 if (IsEqualGUID(riid, &IID_IEnumWorkItems) || IsEqualGUID(riid, &IID_IUnknown))
75 *obj = &This->IEnumWorkItems_iface;
76 IEnumWorkItems_AddRef(iface);
77 return S_OK;
80 *obj = NULL;
81 return E_NOINTERFACE;
84 static ULONG WINAPI EnumWorkItems_AddRef(IEnumWorkItems *iface)
86 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface);
87 ULONG ref = InterlockedIncrement(&This->ref);
88 TRACE("(%p)->(%u)\n", This, ref);
89 return ref;
92 static ULONG WINAPI EnumWorkItems_Release(IEnumWorkItems *iface)
94 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface);
95 ULONG ref = InterlockedDecrement(&This->ref);
97 TRACE("(%p)->(%u)\n", This, ref);
99 if (ref == 0)
101 if (This->handle != INVALID_HANDLE_VALUE)
102 FindClose(This->handle);
103 heap_free(This);
104 InterlockedDecrement(&dll_ref);
107 return ref;
110 static void free_list(LPWSTR *list, LONG count)
112 LONG i;
114 for (i = 0; i < count; i++)
115 CoTaskMemFree(list[i]);
117 CoTaskMemFree(list);
120 static inline BOOL is_file(const WIN32_FIND_DATAW *data)
122 return !(data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
125 static HRESULT WINAPI EnumWorkItems_Next(IEnumWorkItems *iface, ULONG count, LPWSTR **names, ULONG *fetched)
127 static const WCHAR tasksW[] = { '\\','T','a','s','k','s','\\','*',0 };
128 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface);
129 WCHAR path[MAX_PATH];
130 WIN32_FIND_DATAW data;
131 ULONG enumerated, allocated, dummy;
132 LPWSTR *list;
133 HRESULT hr = S_FALSE;
135 TRACE("(%p)->(%u %p %p)\n", This, count, names, fetched);
137 if (!count || !names || (!fetched && count > 1)) return E_INVALIDARG;
139 if (!fetched) fetched = &dummy;
141 *names = NULL;
142 *fetched = 0;
143 enumerated = 0;
144 list = NULL;
146 allocated = 64;
147 list = CoTaskMemAlloc(allocated * sizeof(list[0]));
148 if (!list) return E_OUTOFMEMORY;
150 if (This->handle == INVALID_HANDLE_VALUE)
152 GetWindowsDirectoryW(path, MAX_PATH);
153 lstrcatW(path, tasksW);
154 This->handle = FindFirstFileW(path, &data);
155 if (This->handle == INVALID_HANDLE_VALUE)
156 return S_FALSE;
158 else
160 if (!FindNextFileW(This->handle, &data))
161 return S_FALSE;
166 if (is_file(&data))
168 if (enumerated >= allocated)
170 LPWSTR *new_list;
171 allocated *= 2;
172 new_list = CoTaskMemRealloc(list, allocated * sizeof(list[0]));
173 if (!new_list)
175 hr = E_OUTOFMEMORY;
176 break;
178 list = new_list;
181 list[enumerated] = CoTaskMemAlloc((lstrlenW(data.cFileName) + 1) * sizeof(WCHAR));
182 if (!list[enumerated])
184 hr = E_OUTOFMEMORY;
185 break;
188 lstrcpyW(list[enumerated], data.cFileName);
189 enumerated++;
191 if (enumerated >= count)
193 hr = S_OK;
194 break;
197 } while (FindNextFileW(This->handle, &data));
199 if (FAILED(hr))
200 free_list(list, enumerated);
201 else
203 *fetched = enumerated;
204 *names = list;
207 return hr;
210 static HRESULT WINAPI EnumWorkItems_Skip(IEnumWorkItems *iface, ULONG count)
212 LPWSTR *names;
213 ULONG fetched;
214 HRESULT hr;
216 TRACE("(%p)->(%u)\n", iface, count);
218 hr = EnumWorkItems_Next(iface, count, &names, &fetched);
219 if (SUCCEEDED(hr))
220 free_list(names, fetched);
222 return hr;
225 static HRESULT WINAPI EnumWorkItems_Reset(IEnumWorkItems *iface)
227 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface);
229 TRACE("(%p)\n", This);
231 if (This->handle != INVALID_HANDLE_VALUE)
233 FindClose(This->handle);
234 This->handle = INVALID_HANDLE_VALUE;
237 return S_OK;
240 static HRESULT WINAPI EnumWorkItems_Clone(IEnumWorkItems *iface, IEnumWorkItems **cloned)
242 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface);
243 FIXME("(%p)->(%p): stub\n", This, cloned);
244 return E_NOTIMPL;
247 static const IEnumWorkItemsVtbl EnumWorkItemsVtbl = {
248 EnumWorkItems_QueryInterface,
249 EnumWorkItems_AddRef,
250 EnumWorkItems_Release,
251 EnumWorkItems_Next,
252 EnumWorkItems_Skip,
253 EnumWorkItems_Reset,
254 EnumWorkItems_Clone
257 static HRESULT create_task_enum(IEnumWorkItems **ret)
259 EnumWorkItemsImpl *tasks;
261 *ret = NULL;
263 tasks = heap_alloc(sizeof(*tasks));
264 if (!tasks)
265 return E_OUTOFMEMORY;
267 tasks->IEnumWorkItems_iface.lpVtbl = &EnumWorkItemsVtbl;
268 tasks->ref = 1;
269 tasks->handle = INVALID_HANDLE_VALUE;
271 *ret = &tasks->IEnumWorkItems_iface;
272 InterlockedIncrement(&dll_ref);
273 return S_OK;
276 static HRESULT WINAPI MSTASK_ITaskScheduler_QueryInterface(
277 ITaskScheduler* iface,
278 REFIID riid,
279 void **ppvObject)
281 TaskSchedulerImpl * This = impl_from_ITaskScheduler(iface);
283 TRACE("IID: %s\n", debugstr_guid(riid));
285 if (IsEqualGUID(riid, &IID_IUnknown) ||
286 IsEqualGUID(riid, &IID_ITaskScheduler))
288 *ppvObject = &This->ITaskScheduler_iface;
289 ITaskScheduler_AddRef(iface);
290 return S_OK;
293 *ppvObject = NULL;
294 return E_NOINTERFACE;
297 static ULONG WINAPI MSTASK_ITaskScheduler_AddRef(
298 ITaskScheduler* iface)
300 TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface);
301 TRACE("\n");
302 return InterlockedIncrement(&This->ref);
305 static ULONG WINAPI MSTASK_ITaskScheduler_Release(
306 ITaskScheduler* iface)
308 TaskSchedulerImpl * This = impl_from_ITaskScheduler(iface);
309 ULONG ref;
310 TRACE("\n");
311 ref = InterlockedDecrement(&This->ref);
312 if (ref == 0)
313 TaskSchedulerDestructor(This);
314 return ref;
317 static HRESULT WINAPI MSTASK_ITaskScheduler_SetTargetComputer(
318 ITaskScheduler *iface, LPCWSTR comp_name)
320 TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface);
321 VARIANT v_null, v_comp;
322 HRESULT hr;
324 TRACE("(%p)->(%s)\n", This, debugstr_w(comp_name));
326 V_VT(&v_null) = VT_NULL;
327 V_VT(&v_comp) = VT_BSTR;
328 V_BSTR(&v_comp) = SysAllocString(comp_name);
329 hr = ITaskService_Connect(This->service, v_comp, v_null, v_null, v_null);
330 SysFreeString(V_BSTR(&v_comp));
331 return hr;
334 static HRESULT WINAPI MSTASK_ITaskScheduler_GetTargetComputer(
335 ITaskScheduler *iface, LPWSTR *comp_name)
337 TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface);
338 BSTR bstr;
339 WCHAR *buffer;
340 HRESULT hr;
342 TRACE("(%p)->(%p)\n", This, comp_name);
344 if (!comp_name)
345 return E_INVALIDARG;
347 hr = ITaskService_get_TargetServer(This->service, &bstr);
348 if (hr != S_OK) return hr;
350 /* extra space for two '\' and a zero */
351 buffer = CoTaskMemAlloc((SysStringLen(bstr) + 3) * sizeof(WCHAR));
352 if (buffer)
354 buffer[0] = '\\';
355 buffer[1] = '\\';
356 lstrcpyW(buffer + 2, bstr);
357 *comp_name = buffer;
358 hr = S_OK;
360 else
362 *comp_name = NULL;
363 hr = E_OUTOFMEMORY;
366 SysFreeString(bstr);
367 return hr;
370 static HRESULT WINAPI MSTASK_ITaskScheduler_Enum(
371 ITaskScheduler* iface,
372 IEnumWorkItems **tasks)
374 TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface);
376 TRACE("(%p)->(%p)\n", This, tasks);
378 if (!tasks)
379 return E_INVALIDARG;
381 return create_task_enum(tasks);
384 static HRESULT WINAPI MSTASK_ITaskScheduler_Activate(ITaskScheduler *iface,
385 LPCWSTR task_name, REFIID riid, IUnknown **unknown)
387 ITask *task;
388 IPersistFile *pfile;
389 HRESULT hr;
391 TRACE("%p, %s, %s, %p\n", iface, debugstr_w(task_name), debugstr_guid(riid), unknown);
393 hr = ITaskScheduler_NewWorkItem(iface, task_name, &CLSID_CTask, riid, (IUnknown **)&task);
394 if (hr != S_OK) return hr;
396 hr = ITask_QueryInterface(task, &IID_IPersistFile, (void **)&pfile);
397 if (hr == S_OK)
399 WCHAR *curfile;
401 hr = IPersistFile_GetCurFile(pfile, &curfile);
402 if (hr == S_OK)
404 hr = IPersistFile_Load(pfile, curfile, STGM_READ | STGM_SHARE_DENY_WRITE);
405 CoTaskMemFree(curfile);
408 IPersistFile_Release(pfile);
411 if (hr == S_OK)
412 *unknown = (IUnknown *)task;
413 else
414 ITask_Release(task);
415 return hr;
418 static HRESULT WINAPI MSTASK_ITaskScheduler_Delete(ITaskScheduler *iface, LPCWSTR name)
420 static const WCHAR tasksW[] = { '\\','T','a','s','k','s','\\',0 };
421 static const WCHAR jobW[] = { '.','j','o','b',0 };
422 WCHAR task_name[MAX_PATH];
424 TRACE("%p, %s\n", iface, debugstr_w(name));
426 if (strchrW(name, '.')) return E_INVALIDARG;
428 GetWindowsDirectoryW(task_name, MAX_PATH);
429 lstrcatW(task_name, tasksW);
430 lstrcatW(task_name, name);
431 lstrcatW(task_name, jobW);
433 if (!DeleteFileW(task_name))
434 return HRESULT_FROM_WIN32(GetLastError());
436 return S_OK;
439 static HRESULT WINAPI MSTASK_ITaskScheduler_NewWorkItem(
440 ITaskScheduler* iface,
441 LPCWSTR task_name,
442 REFCLSID rclsid,
443 REFIID riid,
444 IUnknown **task)
446 TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface);
448 TRACE("(%p, %s, %s, %s, %p)\n", iface, debugstr_w(task_name),
449 debugstr_guid(rclsid), debugstr_guid(riid), task);
451 if (!IsEqualGUID(rclsid, &CLSID_CTask))
452 return CLASS_E_CLASSNOTAVAILABLE;
454 if (!IsEqualGUID(riid, &IID_ITask))
455 return E_NOINTERFACE;
457 return TaskConstructor(This->service, task_name, (ITask **)task);
460 static HRESULT WINAPI MSTASK_ITaskScheduler_AddWorkItem(ITaskScheduler *iface, LPCWSTR name, IScheduledWorkItem *item)
462 static const WCHAR tasksW[] = { '\\','T','a','s','k','s','\\',0 };
463 static const WCHAR jobW[] = { '.','j','o','b',0 };
464 WCHAR task_name[MAX_PATH];
465 IPersistFile *pfile;
466 HRESULT hr;
468 TRACE("%p, %s, %p\n", iface, debugstr_w(name), item);
470 if (strchrW(name, '.')) return E_INVALIDARG;
472 GetWindowsDirectoryW(task_name, MAX_PATH);
473 lstrcatW(task_name, tasksW);
474 lstrcatW(task_name, name);
475 lstrcatW(task_name, jobW);
477 hr = IScheduledWorkItem_QueryInterface(item, &IID_IPersistFile, (void **)&pfile);
478 if (hr == S_OK)
480 hr = IPersistFile_Save(pfile, task_name, TRUE);
481 IPersistFile_Release(pfile);
483 return hr;
486 static HRESULT WINAPI MSTASK_ITaskScheduler_IsOfType(
487 ITaskScheduler* iface,
488 LPCWSTR pwszName,
489 REFIID riid)
491 FIXME("%p, %s, %s: stub\n", iface, debugstr_w(pwszName),
492 debugstr_guid(riid));
493 return E_NOTIMPL;
496 static const ITaskSchedulerVtbl MSTASK_ITaskSchedulerVtbl =
498 MSTASK_ITaskScheduler_QueryInterface,
499 MSTASK_ITaskScheduler_AddRef,
500 MSTASK_ITaskScheduler_Release,
501 MSTASK_ITaskScheduler_SetTargetComputer,
502 MSTASK_ITaskScheduler_GetTargetComputer,
503 MSTASK_ITaskScheduler_Enum,
504 MSTASK_ITaskScheduler_Activate,
505 MSTASK_ITaskScheduler_Delete,
506 MSTASK_ITaskScheduler_NewWorkItem,
507 MSTASK_ITaskScheduler_AddWorkItem,
508 MSTASK_ITaskScheduler_IsOfType
511 HRESULT TaskSchedulerConstructor(LPVOID *ppObj)
513 TaskSchedulerImpl *This;
514 ITaskService *service;
515 VARIANT v_null;
516 HRESULT hr;
518 TRACE("(%p)\n", ppObj);
520 hr = CoCreateInstance(&CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, &IID_ITaskService, (void **)&service);
521 if (hr != S_OK) return hr;
523 V_VT(&v_null) = VT_NULL;
524 hr = ITaskService_Connect(service, v_null, v_null, v_null, v_null);
525 if (hr != S_OK)
527 ITaskService_Release(service);
528 return hr;
531 This = heap_alloc(sizeof(*This));
532 if (!This)
534 ITaskService_Release(service);
535 return E_OUTOFMEMORY;
538 This->ITaskScheduler_iface.lpVtbl = &MSTASK_ITaskSchedulerVtbl;
539 This->service = service;
540 This->ref = 1;
542 *ppObj = &This->ITaskScheduler_iface;
543 InterlockedIncrement(&dll_ref);
544 return S_OK;