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
30 #include "mstask_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(mstask
);
37 ITaskScheduler ITaskScheduler_iface
;
39 ITaskService
*service
;
44 IEnumWorkItems IEnumWorkItems_iface
;
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
)
61 ITaskService_Release(This
->service
);
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
);
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
);
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
);
101 InterlockedDecrement(&dll_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
);
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
);
121 static HRESULT WINAPI
EnumWorkItems_Reset(IEnumWorkItems
*iface
)
123 EnumWorkItemsImpl
*This
= impl_from_IEnumWorkItems(iface
);
124 FIXME("(%p): stub\n", This
);
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
);
135 static const IEnumWorkItemsVtbl EnumWorkItemsVtbl
= {
136 EnumWorkItems_QueryInterface
,
137 EnumWorkItems_AddRef
,
138 EnumWorkItems_Release
,
145 static HRESULT
create_task_enum(IEnumWorkItems
**ret
)
147 EnumWorkItemsImpl
*tasks
;
151 tasks
= heap_alloc(sizeof(*tasks
));
153 return E_OUTOFMEMORY
;
155 tasks
->IEnumWorkItems_iface
.lpVtbl
= &EnumWorkItemsVtbl
;
158 *ret
= &tasks
->IEnumWorkItems_iface
;
159 InterlockedIncrement(&dll_ref
);
163 static HRESULT WINAPI
MSTASK_ITaskScheduler_QueryInterface(
164 ITaskScheduler
* iface
,
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
);
181 return E_NOINTERFACE
;
184 static ULONG WINAPI
MSTASK_ITaskScheduler_AddRef(
185 ITaskScheduler
* iface
)
187 TaskSchedulerImpl
*This
= impl_from_ITaskScheduler(iface
);
189 return InterlockedIncrement(&This
->ref
);
192 static ULONG WINAPI
MSTASK_ITaskScheduler_Release(
193 ITaskScheduler
* iface
)
195 TaskSchedulerImpl
* This
= impl_from_ITaskScheduler(iface
);
198 ref
= InterlockedDecrement(&This
->ref
);
200 TaskSchedulerDestructor(This
);
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
;
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
));
221 static HRESULT WINAPI
MSTASK_ITaskScheduler_GetTargetComputer(
222 ITaskScheduler
*iface
, LPWSTR
*comp_name
)
224 TaskSchedulerImpl
*This
= impl_from_ITaskScheduler(iface
);
229 TRACE("(%p)->(%p)\n", This
, comp_name
);
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
));
243 lstrcpyW(buffer
+ 2, bstr
);
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
);
268 return create_task_enum(tasks
);
271 static HRESULT WINAPI
MSTASK_ITaskScheduler_Activate(ITaskScheduler
*iface
,
272 LPCWSTR task_name
, REFIID riid
, IUnknown
**unknown
)
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
);
288 hr
= IPersistFile_GetCurFile(pfile
, &curfile
);
291 hr
= IPersistFile_Load(pfile
, curfile
, STGM_READ
| STGM_SHARE_DENY_WRITE
);
292 CoTaskMemFree(curfile
);
295 IPersistFile_Release(pfile
);
299 *unknown
= (IUnknown
*)task
;
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());
326 static HRESULT WINAPI
MSTASK_ITaskScheduler_NewWorkItem(
327 ITaskScheduler
* iface
,
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
];
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
);
367 hr
= IPersistFile_Save(pfile
, task_name
, TRUE
);
368 IPersistFile_Release(pfile
);
373 static HRESULT WINAPI
MSTASK_ITaskScheduler_IsOfType(
374 ITaskScheduler
* iface
,
378 FIXME("%p, %s, %s: stub\n", iface
, debugstr_w(pwszName
),
379 debugstr_guid(riid
));
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
;
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
);
414 ITaskService_Release(service
);
418 This
= heap_alloc(sizeof(*This
));
421 ITaskService_Release(service
);
422 return E_OUTOFMEMORY
;
425 This
->ITaskScheduler_iface
.lpVtbl
= &MSTASK_ITaskSchedulerVtbl
;
426 This
->service
= service
;
429 *ppObj
= &This
->ITaskScheduler_iface
;
430 InterlockedIncrement(&dll_ref
);