mstask: Implement ITaskScheduler::Delete().
[wine.git] / dlls / mstask / task_scheduler.c
blob416a3218d0c5a2677578182603b85b008592beac
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 } EnumWorkItemsImpl;
48 static inline TaskSchedulerImpl *impl_from_ITaskScheduler(ITaskScheduler *iface)
50 return CONTAINING_RECORD(iface, TaskSchedulerImpl, ITaskScheduler_iface);
53 static inline EnumWorkItemsImpl *impl_from_IEnumWorkItems(IEnumWorkItems *iface)
55 return CONTAINING_RECORD(iface, EnumWorkItemsImpl, IEnumWorkItems_iface);
58 static void TaskSchedulerDestructor(TaskSchedulerImpl *This)
60 TRACE("%p\n", This);
61 ITaskService_Release(This->service);
62 heap_free(This);
63 InterlockedDecrement(&dll_ref);
66 static HRESULT WINAPI EnumWorkItems_QueryInterface(IEnumWorkItems *iface, REFIID riid, void **obj)
68 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface);
70 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
72 if (IsEqualGUID(riid, &IID_IEnumWorkItems) || IsEqualGUID(riid, &IID_IUnknown))
74 *obj = &This->IEnumWorkItems_iface;
75 IEnumWorkItems_AddRef(iface);
76 return S_OK;
79 *obj = NULL;
80 return E_NOINTERFACE;
83 static ULONG WINAPI EnumWorkItems_AddRef(IEnumWorkItems *iface)
85 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface);
86 ULONG ref = InterlockedIncrement(&This->ref);
87 TRACE("(%p)->(%u)\n", This, ref);
88 return ref;
91 static ULONG WINAPI EnumWorkItems_Release(IEnumWorkItems *iface)
93 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface);
94 ULONG ref = InterlockedDecrement(&This->ref);
96 TRACE("(%p)->(%u)\n", This, ref);
98 if (ref == 0)
100 heap_free(This);
101 InterlockedDecrement(&dll_ref);
104 return ref;
107 static HRESULT WINAPI EnumWorkItems_Next(IEnumWorkItems *iface, ULONG count, LPWSTR **names, ULONG *fetched)
109 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface);
110 FIXME("(%p)->(%u %p %p): stub\n", This, count, names, fetched);
111 return E_NOTIMPL;
114 static HRESULT WINAPI EnumWorkItems_Skip(IEnumWorkItems *iface, ULONG count)
116 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface);
117 FIXME("(%p)->(%u): stub\n", This, count);
118 return E_NOTIMPL;
121 static HRESULT WINAPI EnumWorkItems_Reset(IEnumWorkItems *iface)
123 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface);
124 FIXME("(%p): stub\n", This);
125 return E_NOTIMPL;
128 static HRESULT WINAPI EnumWorkItems_Clone(IEnumWorkItems *iface, IEnumWorkItems **cloned)
130 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface);
131 FIXME("(%p)->(%p): stub\n", This, cloned);
132 return E_NOTIMPL;
135 static const IEnumWorkItemsVtbl EnumWorkItemsVtbl = {
136 EnumWorkItems_QueryInterface,
137 EnumWorkItems_AddRef,
138 EnumWorkItems_Release,
139 EnumWorkItems_Next,
140 EnumWorkItems_Skip,
141 EnumWorkItems_Reset,
142 EnumWorkItems_Clone
145 static HRESULT create_task_enum(IEnumWorkItems **ret)
147 EnumWorkItemsImpl *tasks;
149 *ret = NULL;
151 tasks = heap_alloc(sizeof(*tasks));
152 if (!tasks)
153 return E_OUTOFMEMORY;
155 tasks->IEnumWorkItems_iface.lpVtbl = &EnumWorkItemsVtbl;
156 tasks->ref = 1;
158 *ret = &tasks->IEnumWorkItems_iface;
159 InterlockedIncrement(&dll_ref);
160 return S_OK;
163 static HRESULT WINAPI MSTASK_ITaskScheduler_QueryInterface(
164 ITaskScheduler* iface,
165 REFIID riid,
166 void **ppvObject)
168 TaskSchedulerImpl * This = impl_from_ITaskScheduler(iface);
170 TRACE("IID: %s\n", debugstr_guid(riid));
172 if (IsEqualGUID(riid, &IID_IUnknown) ||
173 IsEqualGUID(riid, &IID_ITaskScheduler))
175 *ppvObject = &This->ITaskScheduler_iface;
176 ITaskScheduler_AddRef(iface);
177 return S_OK;
180 *ppvObject = NULL;
181 return E_NOINTERFACE;
184 static ULONG WINAPI MSTASK_ITaskScheduler_AddRef(
185 ITaskScheduler* iface)
187 TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface);
188 TRACE("\n");
189 return InterlockedIncrement(&This->ref);
192 static ULONG WINAPI MSTASK_ITaskScheduler_Release(
193 ITaskScheduler* iface)
195 TaskSchedulerImpl * This = impl_from_ITaskScheduler(iface);
196 ULONG ref;
197 TRACE("\n");
198 ref = InterlockedDecrement(&This->ref);
199 if (ref == 0)
200 TaskSchedulerDestructor(This);
201 return ref;
204 static HRESULT WINAPI MSTASK_ITaskScheduler_SetTargetComputer(
205 ITaskScheduler *iface, LPCWSTR comp_name)
207 TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface);
208 VARIANT v_null, v_comp;
209 HRESULT hr;
211 TRACE("(%p)->(%s)\n", This, debugstr_w(comp_name));
213 V_VT(&v_null) = VT_NULL;
214 V_VT(&v_comp) = VT_BSTR;
215 V_BSTR(&v_comp) = SysAllocString(comp_name);
216 hr = ITaskService_Connect(This->service, v_comp, v_null, v_null, v_null);
217 SysFreeString(V_BSTR(&v_comp));
218 return hr;
221 static HRESULT WINAPI MSTASK_ITaskScheduler_GetTargetComputer(
222 ITaskScheduler *iface, LPWSTR *comp_name)
224 TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface);
225 BSTR bstr;
226 WCHAR *buffer;
227 HRESULT hr;
229 TRACE("(%p)->(%p)\n", This, comp_name);
231 if (!comp_name)
232 return E_INVALIDARG;
234 hr = ITaskService_get_TargetServer(This->service, &bstr);
235 if (hr != S_OK) return hr;
237 /* extra space for two '\' and a zero */
238 buffer = CoTaskMemAlloc((SysStringLen(bstr) + 3) * sizeof(WCHAR));
239 if (buffer)
241 buffer[0] = '\\';
242 buffer[1] = '\\';
243 lstrcpyW(buffer + 2, bstr);
244 *comp_name = buffer;
245 hr = S_OK;
247 else
249 *comp_name = NULL;
250 hr = E_OUTOFMEMORY;
253 SysFreeString(bstr);
254 return hr;
257 static HRESULT WINAPI MSTASK_ITaskScheduler_Enum(
258 ITaskScheduler* iface,
259 IEnumWorkItems **tasks)
261 TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface);
263 TRACE("(%p)->(%p)\n", This, tasks);
265 if (!tasks)
266 return E_INVALIDARG;
268 return create_task_enum(tasks);
271 static HRESULT WINAPI MSTASK_ITaskScheduler_Activate(ITaskScheduler *iface,
272 LPCWSTR task_name, REFIID riid, IUnknown **unknown)
274 ITask *task;
275 IPersistFile *pfile;
276 HRESULT hr;
278 TRACE("%p, %s, %s, %p\n", iface, debugstr_w(task_name), debugstr_guid(riid), unknown);
280 hr = ITaskScheduler_NewWorkItem(iface, task_name, &CLSID_CTask, riid, (IUnknown **)&task);
281 if (hr != S_OK) return hr;
283 hr = ITask_QueryInterface(task, &IID_IPersistFile, (void **)&pfile);
284 if (hr == S_OK)
286 WCHAR *curfile;
288 hr = IPersistFile_GetCurFile(pfile, &curfile);
289 if (hr == S_OK)
291 hr = IPersistFile_Load(pfile, curfile, STGM_READ | STGM_SHARE_DENY_WRITE);
292 CoTaskMemFree(curfile);
295 IPersistFile_Release(pfile);
298 if (hr == S_OK)
299 *unknown = (IUnknown *)task;
300 else
301 ITask_Release(task);
302 return hr;
305 static HRESULT WINAPI MSTASK_ITaskScheduler_Delete(ITaskScheduler *iface, LPCWSTR name)
307 static const WCHAR tasksW[] = { '\\','T','a','s','k','s','\\',0 };
308 static const WCHAR jobW[] = { '.','j','o','b',0 };
309 WCHAR task_name[MAX_PATH];
311 TRACE("%p, %s\n", iface, debugstr_w(name));
313 if (strchrW(name, '.')) return E_INVALIDARG;
315 GetWindowsDirectoryW(task_name, MAX_PATH);
316 lstrcatW(task_name, tasksW);
317 lstrcatW(task_name, name);
318 lstrcatW(task_name, jobW);
320 if (!DeleteFileW(task_name))
321 return HRESULT_FROM_WIN32(GetLastError());
323 return S_OK;
326 static HRESULT WINAPI MSTASK_ITaskScheduler_NewWorkItem(
327 ITaskScheduler* iface,
328 LPCWSTR task_name,
329 REFCLSID rclsid,
330 REFIID riid,
331 IUnknown **task)
333 TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface);
335 TRACE("(%p, %s, %s, %s, %p)\n", iface, debugstr_w(task_name),
336 debugstr_guid(rclsid), debugstr_guid(riid), task);
338 if (!IsEqualGUID(rclsid, &CLSID_CTask))
339 return CLASS_E_CLASSNOTAVAILABLE;
341 if (!IsEqualGUID(riid, &IID_ITask))
342 return E_NOINTERFACE;
344 return TaskConstructor(This->service, task_name, (ITask **)task);
347 static HRESULT WINAPI MSTASK_ITaskScheduler_AddWorkItem(ITaskScheduler *iface, LPCWSTR name, IScheduledWorkItem *item)
349 static const WCHAR tasksW[] = { '\\','T','a','s','k','s','\\',0 };
350 static const WCHAR jobW[] = { '.','j','o','b',0 };
351 WCHAR task_name[MAX_PATH];
352 IPersistFile *pfile;
353 HRESULT hr;
355 TRACE("%p, %s, %p\n", iface, debugstr_w(name), item);
357 if (strchrW(name, '.')) return E_INVALIDARG;
359 GetWindowsDirectoryW(task_name, MAX_PATH);
360 lstrcatW(task_name, tasksW);
361 lstrcatW(task_name, name);
362 lstrcatW(task_name, jobW);
364 hr = IScheduledWorkItem_QueryInterface(item, &IID_IPersistFile, (void **)&pfile);
365 if (hr == S_OK)
367 hr = IPersistFile_Save(pfile, task_name, TRUE);
368 IPersistFile_Release(pfile);
370 return hr;
373 static HRESULT WINAPI MSTASK_ITaskScheduler_IsOfType(
374 ITaskScheduler* iface,
375 LPCWSTR pwszName,
376 REFIID riid)
378 FIXME("%p, %s, %s: stub\n", iface, debugstr_w(pwszName),
379 debugstr_guid(riid));
380 return E_NOTIMPL;
383 static const ITaskSchedulerVtbl MSTASK_ITaskSchedulerVtbl =
385 MSTASK_ITaskScheduler_QueryInterface,
386 MSTASK_ITaskScheduler_AddRef,
387 MSTASK_ITaskScheduler_Release,
388 MSTASK_ITaskScheduler_SetTargetComputer,
389 MSTASK_ITaskScheduler_GetTargetComputer,
390 MSTASK_ITaskScheduler_Enum,
391 MSTASK_ITaskScheduler_Activate,
392 MSTASK_ITaskScheduler_Delete,
393 MSTASK_ITaskScheduler_NewWorkItem,
394 MSTASK_ITaskScheduler_AddWorkItem,
395 MSTASK_ITaskScheduler_IsOfType
398 HRESULT TaskSchedulerConstructor(LPVOID *ppObj)
400 TaskSchedulerImpl *This;
401 ITaskService *service;
402 VARIANT v_null;
403 HRESULT hr;
405 TRACE("(%p)\n", ppObj);
407 hr = CoCreateInstance(&CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, &IID_ITaskService, (void **)&service);
408 if (hr != S_OK) return hr;
410 V_VT(&v_null) = VT_NULL;
411 hr = ITaskService_Connect(service, v_null, v_null, v_null, v_null);
412 if (hr != S_OK)
414 ITaskService_Release(service);
415 return hr;
418 This = heap_alloc(sizeof(*This));
419 if (!This)
421 ITaskService_Release(service);
422 return E_OUTOFMEMORY;
425 This->ITaskScheduler_iface.lpVtbl = &MSTASK_ITaskSchedulerVtbl;
426 This->service = service;
427 This->ref = 1;
429 *ppObj = &This->ITaskScheduler_iface;
430 InterlockedIncrement(&dll_ref);
431 return S_OK;