2 * Copyright 2014 Dmitry Timoshkov
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "taskschd_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(taskschd
);
37 ITaskFolder ITaskFolder_iface
;
42 static inline TaskFolder
*impl_from_ITaskFolder(ITaskFolder
*iface
)
44 return CONTAINING_RECORD(iface
, TaskFolder
, ITaskFolder_iface
);
47 static ULONG WINAPI
TaskFolder_AddRef(ITaskFolder
*iface
)
49 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
50 return InterlockedIncrement(&folder
->ref
);
53 static ULONG WINAPI
TaskFolder_Release(ITaskFolder
*iface
)
55 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
56 LONG ref
= InterlockedDecrement(&folder
->ref
);
60 TRACE("destroying %p\n", iface
);
61 heap_free(folder
->path
);
68 static HRESULT WINAPI
TaskFolder_QueryInterface(ITaskFolder
*iface
, REFIID riid
, void **obj
)
70 if (!riid
|| !obj
) return E_INVALIDARG
;
72 TRACE("%p,%s,%p\n", iface
, debugstr_guid(riid
), obj
);
74 if (IsEqualGUID(riid
, &IID_ITaskFolder
) ||
75 IsEqualGUID(riid
, &IID_IDispatch
) ||
76 IsEqualGUID(riid
, &IID_IUnknown
))
78 ITaskFolder_AddRef(iface
);
83 FIXME("interface %s is not implemented\n", debugstr_guid(riid
));
88 static HRESULT WINAPI
TaskFolder_GetTypeInfoCount(ITaskFolder
*iface
, UINT
*count
)
90 FIXME("%p,%p: stub\n", iface
, count
);
94 static HRESULT WINAPI
TaskFolder_GetTypeInfo(ITaskFolder
*iface
, UINT index
, LCID lcid
, ITypeInfo
**info
)
96 FIXME("%p,%u,%u,%p: stub\n", iface
, index
, lcid
, info
);
100 static HRESULT WINAPI
TaskFolder_GetIDsOfNames(ITaskFolder
*iface
, REFIID riid
, LPOLESTR
*names
,
101 UINT count
, LCID lcid
, DISPID
*dispid
)
103 FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface
, debugstr_guid(riid
), names
, count
, lcid
, dispid
);
107 static HRESULT WINAPI
TaskFolder_Invoke(ITaskFolder
*iface
, DISPID dispid
, REFIID riid
, LCID lcid
, WORD flags
,
108 DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*argerr
)
110 FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface
, dispid
, debugstr_guid(riid
), lcid
, flags
,
111 params
, result
, excepinfo
, argerr
);
115 static HRESULT WINAPI
TaskFolder_get_Name(ITaskFolder
*iface
, BSTR
*name
)
117 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
120 TRACE("%p,%p\n", iface
, name
);
122 if (!name
) return E_POINTER
;
124 p_name
= wcsrchr(folder
->path
, '\\');
126 p_name
= folder
->path
;
128 if (p_name
[1] != 0) p_name
++;
130 *name
= SysAllocString(p_name
);
131 if (!*name
) return E_OUTOFMEMORY
;
136 static HRESULT WINAPI
TaskFolder_get_Path(ITaskFolder
*iface
, BSTR
*path
)
138 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
140 TRACE("%p,%p\n", iface
, path
);
142 if (!path
) return E_POINTER
;
144 *path
= SysAllocString(folder
->path
);
145 if (!*path
) return E_OUTOFMEMORY
;
150 static HRESULT WINAPI
TaskFolder_GetFolder(ITaskFolder
*iface
, BSTR path
, ITaskFolder
**new_folder
)
152 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
154 TRACE("%p,%s,%p\n", iface
, debugstr_w(path
), folder
);
156 if (!path
) return E_INVALIDARG
;
157 if (!new_folder
) return E_POINTER
;
159 return TaskFolder_create(folder
->path
, path
, new_folder
, FALSE
);
162 static HRESULT WINAPI
TaskFolder_GetFolders(ITaskFolder
*iface
, LONG flags
, ITaskFolderCollection
**folders
)
164 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
166 TRACE("%p,%x,%p: stub\n", iface
, flags
, folders
);
168 if (!folders
) return E_POINTER
;
171 FIXME("unsupported flags %x\n", flags
);
173 return TaskFolderCollection_create(folder
->path
, folders
);
176 static inline BOOL
is_variant_null(const VARIANT
*var
)
178 return V_VT(var
) == VT_EMPTY
|| V_VT(var
) == VT_NULL
||
179 (V_VT(var
) == VT_BSTR
&& (V_BSTR(var
) == NULL
|| !*V_BSTR(var
)));
182 static HRESULT WINAPI
TaskFolder_CreateFolder(ITaskFolder
*iface
, BSTR path
, VARIANT sddl
, ITaskFolder
**new_folder
)
184 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
185 ITaskFolder
*tmp_folder
= NULL
;
188 TRACE("%p,%s,%s,%p\n", iface
, debugstr_w(path
), debugstr_variant(&sddl
), folder
);
190 if (!path
) return E_INVALIDARG
;
192 if (!new_folder
) new_folder
= &tmp_folder
;
194 if (!is_variant_null(&sddl
))
195 FIXME("security descriptor %s is ignored\n", debugstr_variant(&sddl
));
197 hr
= TaskFolder_create(folder
->path
, path
, new_folder
, TRUE
);
199 ITaskFolder_Release(tmp_folder
);
204 WCHAR
*get_full_path(const WCHAR
*parent
, const WCHAR
*path
)
206 static const WCHAR bslash
[] = { '\\', 0 };
210 if (path
) len
= lstrlenW(path
);
212 if (parent
) len
+= lstrlenW(parent
);
214 /* +1 if parent is not '\' terminated */
215 folder_path
= heap_alloc((len
+ 2) * sizeof(WCHAR
));
216 if (!folder_path
) return NULL
;
221 lstrcpyW(folder_path
, parent
);
225 len
= lstrlenW(folder_path
);
226 if (!len
|| folder_path
[len
- 1] != '\\')
227 lstrcatW(folder_path
, bslash
);
229 while (*path
== '\\') path
++;
230 lstrcatW(folder_path
, path
);
233 len
= lstrlenW(folder_path
);
235 lstrcatW(folder_path
, bslash
);
240 static HRESULT WINAPI
TaskFolder_DeleteFolder(ITaskFolder
*iface
, BSTR name
, LONG flags
)
242 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
246 TRACE("%p,%s,%x\n", iface
, debugstr_w(name
), flags
);
248 if (!name
|| !*name
) return E_ACCESSDENIED
;
251 FIXME("unsupported flags %x\n", flags
);
253 folder_path
= get_full_path(folder
->path
, name
);
254 if (!folder_path
) return E_OUTOFMEMORY
;
256 hr
= SchRpcDelete(folder_path
, 0);
257 heap_free(folder_path
);
261 static HRESULT WINAPI
TaskFolder_GetTask(ITaskFolder
*iface
, BSTR name
, IRegisteredTask
**task
)
263 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
264 ITaskDefinition
*taskdef
;
267 TRACE("%p,%s,%p\n", iface
, debugstr_w(name
), task
);
269 if (!task
) return E_POINTER
;
271 hr
= TaskDefinition_create(&taskdef
);
272 if (hr
!= S_OK
) return hr
;
274 hr
= RegisteredTask_create(folder
->path
, name
, taskdef
, 0, 0, task
, FALSE
);
276 ITaskDefinition_Release(taskdef
);
280 static HRESULT WINAPI
TaskFolder_GetTasks(ITaskFolder
*iface
, LONG flags
, IRegisteredTaskCollection
**tasks
)
282 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
284 TRACE("%p,%x,%p: stub\n", iface
, flags
, tasks
);
286 if (!tasks
) return E_POINTER
;
288 return RegisteredTaskCollection_create(folder
->path
, tasks
);
291 static HRESULT WINAPI
TaskFolder_DeleteTask(ITaskFolder
*iface
, BSTR name
, LONG flags
)
293 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
297 TRACE("%p,%s,%x\n", iface
, debugstr_w(name
), flags
);
299 if (!name
|| !*name
) return E_ACCESSDENIED
;
302 FIXME("unsupported flags %x\n", flags
);
304 folder_path
= get_full_path(folder
->path
, name
);
305 if (!folder_path
) return E_OUTOFMEMORY
;
307 hr
= SchRpcDelete(folder_path
, 0);
308 heap_free(folder_path
);
312 static HRESULT WINAPI
TaskFolder_RegisterTask(ITaskFolder
*iface
, BSTR name
, BSTR xml
, LONG flags
,
313 VARIANT user
, VARIANT password
, TASK_LOGON_TYPE logon
,
314 VARIANT sddl
, IRegisteredTask
**task
)
316 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
317 IRegisteredTask
*regtask
= NULL
;
318 ITaskDefinition
*taskdef
;
321 TRACE("%p,%s,%s,%x,%s,%s,%d,%s,%p\n", iface
, debugstr_w(name
), debugstr_w(xml
), flags
,
322 debugstr_variant(&user
), debugstr_variant(&password
), logon
, debugstr_variant(&sddl
), task
);
324 if (!xml
) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
);
326 if (!task
) task
= ®task
;
328 hr
= TaskDefinition_create(&taskdef
);
329 if (hr
!= S_OK
) return hr
;
331 hr
= ITaskDefinition_put_XmlText(taskdef
, xml
);
333 hr
= RegisteredTask_create(folder
->path
, name
, taskdef
, flags
, logon
, task
, TRUE
);
336 ITaskDefinition_Release(taskdef
);
339 IRegisteredTask_Release(regtask
);
344 static HRESULT WINAPI
TaskFolder_RegisterTaskDefinition(ITaskFolder
*iface
, BSTR name
, ITaskDefinition
*definition
, LONG flags
,
345 VARIANT user
, VARIANT password
, TASK_LOGON_TYPE logon
,
346 VARIANT sddl
, IRegisteredTask
**task
)
348 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
349 IRegisteredTask
*regtask
= NULL
;
352 FIXME("%p,%s,%p,%x,%s,%s,%d,%s,%p: stub\n", iface
, debugstr_w(name
), definition
, flags
,
353 debugstr_variant(&user
), debugstr_variant(&password
), logon
, debugstr_variant(&sddl
), task
);
355 if (!is_variant_null(&sddl
))
356 FIXME("security descriptor %s is ignored\n", debugstr_variant(&sddl
));
358 if (!is_variant_null(&user
) || !is_variant_null(&password
))
359 FIXME("user/password are ignored\n");
361 if (!task
) task
= ®task
;
363 ITaskDefinition_AddRef(definition
);
364 hr
= RegisteredTask_create(folder
->path
, name
, definition
, flags
, logon
, task
, TRUE
);
366 ITaskDefinition_Release(definition
);
369 IRegisteredTask_Release(regtask
);
374 static HRESULT WINAPI
TaskFolder_GetSecurityDescriptor(ITaskFolder
*iface
, LONG info
, BSTR
*sddl
)
376 FIXME("%p,%x,%p: stub\n", iface
, info
, sddl
);
380 static HRESULT WINAPI
TaskFolder_SetSecurityDescriptor(ITaskFolder
*iface
, BSTR sddl
, LONG flags
)
382 FIXME("%p,%s,%x: stub\n", iface
, debugstr_w(sddl
), flags
);
386 static const ITaskFolderVtbl TaskFolder_vtbl
=
388 TaskFolder_QueryInterface
,
391 TaskFolder_GetTypeInfoCount
,
392 TaskFolder_GetTypeInfo
,
393 TaskFolder_GetIDsOfNames
,
397 TaskFolder_GetFolder
,
398 TaskFolder_GetFolders
,
399 TaskFolder_CreateFolder
,
400 TaskFolder_DeleteFolder
,
403 TaskFolder_DeleteTask
,
404 TaskFolder_RegisterTask
,
405 TaskFolder_RegisterTaskDefinition
,
406 TaskFolder_GetSecurityDescriptor
,
407 TaskFolder_SetSecurityDescriptor
410 HRESULT
TaskFolder_create(const WCHAR
*parent
, const WCHAR
*path
, ITaskFolder
**obj
, BOOL create
)
418 int len
= lstrlenW(path
);
419 if (len
&& path
[len
- 1] == '\\') return HRESULT_FROM_WIN32(ERROR_INVALID_NAME
);
422 folder_path
= get_full_path(parent
, path
);
423 if (!folder_path
) return E_OUTOFMEMORY
;
427 hr
= SchRpcCreateFolder(folder_path
, NULL
, 0);
431 DWORD start_index
, count
, i
;
436 hr
= SchRpcEnumFolders(folder_path
, 0, &start_index
, 0, &count
, &names
);
439 for (i
= 0; i
< count
; i
++)
440 MIDL_user_free(names
[i
]);
441 MIDL_user_free(names
);
445 if (hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
))
446 hr
= HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
);
452 heap_free(folder_path
);
456 folder
= heap_alloc(sizeof(*folder
));
459 heap_free(folder_path
);
460 return E_OUTOFMEMORY
;
463 folder
->ITaskFolder_iface
.lpVtbl
= &TaskFolder_vtbl
;
465 folder
->path
= folder_path
;
466 *obj
= &folder
->ITaskFolder_iface
;
468 TRACE("created %p\n", *obj
);