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
;
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
)
62 ITaskService_Release(This
->service
);
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
);
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
);
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
);
101 if (This
->handle
!= INVALID_HANDLE_VALUE
)
102 FindClose(This
->handle
);
104 InterlockedDecrement(&dll_ref
);
110 static void free_list(LPWSTR
*list
, LONG count
)
114 for (i
= 0; i
< count
; i
++)
115 CoTaskMemFree(list
[i
]);
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 EnumWorkItemsImpl
*This
= impl_from_IEnumWorkItems(iface
);
128 WCHAR path
[MAX_PATH
];
129 WIN32_FIND_DATAW data
;
130 ULONG enumerated
, allocated
, dummy
;
132 HRESULT hr
= S_FALSE
;
134 TRACE("(%p)->(%u %p %p)\n", This
, count
, names
, fetched
);
136 if (!count
|| !names
|| (!fetched
&& count
> 1)) return E_INVALIDARG
;
138 if (!fetched
) fetched
= &dummy
;
145 if (This
->handle
== INVALID_HANDLE_VALUE
)
147 GetWindowsDirectoryW(path
, MAX_PATH
);
148 lstrcatW(path
, L
"\\Tasks\\*");
149 This
->handle
= FindFirstFileW(path
, &data
);
150 if (This
->handle
== INVALID_HANDLE_VALUE
)
155 if (!FindNextFileW(This
->handle
, &data
))
160 list
= CoTaskMemAlloc(allocated
* sizeof(list
[0]));
161 if (!list
) return E_OUTOFMEMORY
;
167 if (enumerated
>= allocated
)
171 new_list
= CoTaskMemRealloc(list
, allocated
* sizeof(list
[0]));
180 list
[enumerated
] = CoTaskMemAlloc((lstrlenW(data
.cFileName
) + 1) * sizeof(WCHAR
));
181 if (!list
[enumerated
])
187 lstrcpyW(list
[enumerated
], data
.cFileName
);
190 if (enumerated
>= count
)
196 } while (FindNextFileW(This
->handle
, &data
));
199 free_list(list
, enumerated
);
202 *fetched
= enumerated
;
209 static HRESULT WINAPI
EnumWorkItems_Skip(IEnumWorkItems
*iface
, ULONG count
)
215 TRACE("(%p)->(%u)\n", iface
, count
);
217 hr
= EnumWorkItems_Next(iface
, count
, &names
, &fetched
);
219 free_list(names
, fetched
);
224 static HRESULT WINAPI
EnumWorkItems_Reset(IEnumWorkItems
*iface
)
226 EnumWorkItemsImpl
*This
= impl_from_IEnumWorkItems(iface
);
228 TRACE("(%p)\n", This
);
230 if (This
->handle
!= INVALID_HANDLE_VALUE
)
232 FindClose(This
->handle
);
233 This
->handle
= INVALID_HANDLE_VALUE
;
239 static HRESULT WINAPI
EnumWorkItems_Clone(IEnumWorkItems
*iface
, IEnumWorkItems
**cloned
)
241 EnumWorkItemsImpl
*This
= impl_from_IEnumWorkItems(iface
);
242 FIXME("(%p)->(%p): stub\n", This
, cloned
);
246 static const IEnumWorkItemsVtbl EnumWorkItemsVtbl
= {
247 EnumWorkItems_QueryInterface
,
248 EnumWorkItems_AddRef
,
249 EnumWorkItems_Release
,
256 static HRESULT
create_task_enum(IEnumWorkItems
**ret
)
258 EnumWorkItemsImpl
*tasks
;
262 tasks
= heap_alloc(sizeof(*tasks
));
264 return E_OUTOFMEMORY
;
266 tasks
->IEnumWorkItems_iface
.lpVtbl
= &EnumWorkItemsVtbl
;
268 tasks
->handle
= INVALID_HANDLE_VALUE
;
270 *ret
= &tasks
->IEnumWorkItems_iface
;
271 InterlockedIncrement(&dll_ref
);
275 static HRESULT WINAPI
MSTASK_ITaskScheduler_QueryInterface(
276 ITaskScheduler
* iface
,
280 TaskSchedulerImpl
* This
= impl_from_ITaskScheduler(iface
);
282 TRACE("IID: %s\n", debugstr_guid(riid
));
284 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
285 IsEqualGUID(riid
, &IID_ITaskScheduler
))
287 *ppvObject
= &This
->ITaskScheduler_iface
;
288 ITaskScheduler_AddRef(iface
);
293 return E_NOINTERFACE
;
296 static ULONG WINAPI
MSTASK_ITaskScheduler_AddRef(
297 ITaskScheduler
* iface
)
299 TaskSchedulerImpl
*This
= impl_from_ITaskScheduler(iface
);
301 return InterlockedIncrement(&This
->ref
);
304 static ULONG WINAPI
MSTASK_ITaskScheduler_Release(
305 ITaskScheduler
* iface
)
307 TaskSchedulerImpl
* This
= impl_from_ITaskScheduler(iface
);
310 ref
= InterlockedDecrement(&This
->ref
);
312 TaskSchedulerDestructor(This
);
316 static HRESULT WINAPI
MSTASK_ITaskScheduler_SetTargetComputer(
317 ITaskScheduler
*iface
, LPCWSTR comp_name
)
319 TaskSchedulerImpl
*This
= impl_from_ITaskScheduler(iface
);
320 VARIANT v_null
, v_comp
;
323 TRACE("(%p)->(%s)\n", This
, debugstr_w(comp_name
));
325 V_VT(&v_null
) = VT_NULL
;
326 V_VT(&v_comp
) = VT_BSTR
;
327 V_BSTR(&v_comp
) = SysAllocString(comp_name
);
328 hr
= ITaskService_Connect(This
->service
, v_comp
, v_null
, v_null
, v_null
);
329 SysFreeString(V_BSTR(&v_comp
));
333 static HRESULT WINAPI
MSTASK_ITaskScheduler_GetTargetComputer(
334 ITaskScheduler
*iface
, LPWSTR
*comp_name
)
336 TaskSchedulerImpl
*This
= impl_from_ITaskScheduler(iface
);
341 TRACE("(%p)->(%p)\n", This
, comp_name
);
346 hr
= ITaskService_get_TargetServer(This
->service
, &bstr
);
347 if (hr
!= S_OK
) return hr
;
349 /* extra space for two '\' and a zero */
350 buffer
= CoTaskMemAlloc((SysStringLen(bstr
) + 3) * sizeof(WCHAR
));
355 lstrcpyW(buffer
+ 2, bstr
);
369 static HRESULT WINAPI
MSTASK_ITaskScheduler_Enum(
370 ITaskScheduler
* iface
,
371 IEnumWorkItems
**tasks
)
373 TaskSchedulerImpl
*This
= impl_from_ITaskScheduler(iface
);
375 TRACE("(%p)->(%p)\n", This
, tasks
);
380 return create_task_enum(tasks
);
383 static HRESULT WINAPI
MSTASK_ITaskScheduler_Activate(ITaskScheduler
*iface
,
384 LPCWSTR task_name
, REFIID riid
, IUnknown
**unknown
)
390 TRACE("%p, %s, %s, %p\n", iface
, debugstr_w(task_name
), debugstr_guid(riid
), unknown
);
392 hr
= ITaskScheduler_NewWorkItem(iface
, task_name
, &CLSID_CTask
, riid
, (IUnknown
**)&task
);
393 if (hr
!= S_OK
) return hr
;
395 hr
= ITask_QueryInterface(task
, &IID_IPersistFile
, (void **)&pfile
);
400 hr
= IPersistFile_GetCurFile(pfile
, &curfile
);
403 hr
= IPersistFile_Load(pfile
, curfile
, STGM_READ
| STGM_SHARE_DENY_WRITE
);
404 CoTaskMemFree(curfile
);
407 IPersistFile_Release(pfile
);
411 *unknown
= (IUnknown
*)task
;
417 static HRESULT WINAPI
MSTASK_ITaskScheduler_Delete(ITaskScheduler
*iface
, LPCWSTR name
)
419 WCHAR task_name
[MAX_PATH
];
421 TRACE("%p, %s\n", iface
, debugstr_w(name
));
423 if (wcschr(name
, '.')) return E_INVALIDARG
;
425 GetWindowsDirectoryW(task_name
, MAX_PATH
);
426 lstrcatW(task_name
, L
"\\Tasks\\");
427 lstrcatW(task_name
, name
);
428 lstrcatW(task_name
, L
".job");
430 if (!DeleteFileW(task_name
))
431 return HRESULT_FROM_WIN32(GetLastError());
436 static HRESULT WINAPI
MSTASK_ITaskScheduler_NewWorkItem(
437 ITaskScheduler
* iface
,
443 TaskSchedulerImpl
*This
= impl_from_ITaskScheduler(iface
);
445 TRACE("(%p, %s, %s, %s, %p)\n", iface
, debugstr_w(task_name
),
446 debugstr_guid(rclsid
), debugstr_guid(riid
), task
);
448 if (!IsEqualGUID(rclsid
, &CLSID_CTask
))
449 return CLASS_E_CLASSNOTAVAILABLE
;
451 if (!IsEqualGUID(riid
, &IID_ITask
))
452 return E_NOINTERFACE
;
454 return TaskConstructor(This
->service
, task_name
, (ITask
**)task
);
457 static HRESULT WINAPI
MSTASK_ITaskScheduler_AddWorkItem(ITaskScheduler
*iface
, LPCWSTR name
, IScheduledWorkItem
*item
)
459 WCHAR task_name
[MAX_PATH
];
463 TRACE("%p, %s, %p\n", iface
, debugstr_w(name
), item
);
465 if (wcschr(name
, '.')) return E_INVALIDARG
;
467 GetWindowsDirectoryW(task_name
, MAX_PATH
);
468 lstrcatW(task_name
, L
"\\Tasks\\");
469 lstrcatW(task_name
, name
);
470 lstrcatW(task_name
, L
".job");
472 hr
= IScheduledWorkItem_QueryInterface(item
, &IID_IPersistFile
, (void **)&pfile
);
475 hr
= IPersistFile_Save(pfile
, task_name
, TRUE
);
476 IPersistFile_Release(pfile
);
481 static HRESULT WINAPI
MSTASK_ITaskScheduler_IsOfType(
482 ITaskScheduler
* iface
,
486 FIXME("%p, %s, %s: stub\n", iface
, debugstr_w(pwszName
),
487 debugstr_guid(riid
));
491 static const ITaskSchedulerVtbl MSTASK_ITaskSchedulerVtbl
=
493 MSTASK_ITaskScheduler_QueryInterface
,
494 MSTASK_ITaskScheduler_AddRef
,
495 MSTASK_ITaskScheduler_Release
,
496 MSTASK_ITaskScheduler_SetTargetComputer
,
497 MSTASK_ITaskScheduler_GetTargetComputer
,
498 MSTASK_ITaskScheduler_Enum
,
499 MSTASK_ITaskScheduler_Activate
,
500 MSTASK_ITaskScheduler_Delete
,
501 MSTASK_ITaskScheduler_NewWorkItem
,
502 MSTASK_ITaskScheduler_AddWorkItem
,
503 MSTASK_ITaskScheduler_IsOfType
506 HRESULT
TaskSchedulerConstructor(LPVOID
*ppObj
)
508 TaskSchedulerImpl
*This
;
509 ITaskService
*service
;
513 TRACE("(%p)\n", ppObj
);
515 hr
= CoCreateInstance(&CLSID_TaskScheduler
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ITaskService
, (void **)&service
);
516 if (hr
!= S_OK
) return hr
;
518 V_VT(&v_null
) = VT_NULL
;
519 hr
= ITaskService_Connect(service
, v_null
, v_null
, v_null
, v_null
);
522 ITaskService_Release(service
);
526 This
= heap_alloc(sizeof(*This
));
529 ITaskService_Release(service
);
530 return E_OUTOFMEMORY
;
533 This
->ITaskScheduler_iface
.lpVtbl
= &MSTASK_ITaskSchedulerVtbl
;
534 This
->service
= service
;
537 *ppObj
= &This
->ITaskScheduler_iface
;
538 InterlockedIncrement(&dll_ref
);