dmusic: Avoid swallowing collection Load failures.
[wine.git] / dlls / taskschd / folder.c
blob87eac46f8823753f928b86064615e6f20aabbf95
1 /*
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
19 #include <stdarg.h>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winreg.h"
26 #include "objbase.h"
27 #include "taskschd.h"
28 #include "schrpc.h"
29 #include "taskschd_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(taskschd);
35 typedef struct
37 ITaskFolder ITaskFolder_iface;
38 LONG ref;
39 WCHAR *path;
40 } TaskFolder;
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);
58 if (!ref)
60 TRACE("destroying %p\n", iface);
61 free(folder->path);
62 free(folder);
65 return ref;
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);
79 *obj = iface;
80 return S_OK;
83 FIXME("interface %s is not implemented\n", debugstr_guid(riid));
84 *obj = NULL;
85 return E_NOINTERFACE;
88 static HRESULT WINAPI TaskFolder_GetTypeInfoCount(ITaskFolder *iface, UINT *count)
90 FIXME("%p,%p: stub\n", iface, count);
91 return E_NOTIMPL;
94 static HRESULT WINAPI TaskFolder_GetTypeInfo(ITaskFolder *iface, UINT index, LCID lcid, ITypeInfo **info)
96 FIXME("%p,%u,%lu,%p: stub\n", iface, index, lcid, info);
97 return E_NOTIMPL;
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,%lu,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid);
104 return E_NOTIMPL;
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,%ld,%s,%04lx,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags,
111 params, result, excepinfo, argerr);
112 return E_NOTIMPL;
115 static HRESULT WINAPI TaskFolder_get_Name(ITaskFolder *iface, BSTR *name)
117 TaskFolder *folder = impl_from_ITaskFolder(iface);
118 const WCHAR *p_name;
120 TRACE("%p,%p\n", iface, name);
122 if (!name) return E_POINTER;
124 p_name = wcsrchr(folder->path, '\\');
125 if (!p_name)
126 p_name = folder->path;
127 else
128 if (p_name[1] != 0) p_name++;
130 *name = SysAllocString(p_name);
131 if (!*name) return E_OUTOFMEMORY;
133 return S_OK;
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;
147 return S_OK;
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,%lx,%p: stub\n", iface, flags, folders);
168 if (!folders) return E_POINTER;
170 if (flags)
171 FIXME("unsupported flags %lx\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;
186 HRESULT hr;
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);
198 if (tmp_folder)
199 ITaskFolder_Release(tmp_folder);
201 return hr;
204 WCHAR *get_full_path(const WCHAR *parent, const WCHAR *path)
206 WCHAR *folder_path;
207 int len = 0;
209 if (path) len = lstrlenW(path);
211 if (parent) len += lstrlenW(parent);
213 /* +1 if parent is not '\' terminated */
214 folder_path = malloc((len + 2) * sizeof(WCHAR));
215 if (!folder_path) return NULL;
217 folder_path[0] = 0;
219 if (parent)
220 lstrcpyW(folder_path, parent);
222 if (path && *path)
224 len = lstrlenW(folder_path);
225 if (!len || folder_path[len - 1] != '\\')
226 lstrcatW(folder_path, L"\\");
228 while (*path == '\\') path++;
229 lstrcatW(folder_path, path);
232 len = lstrlenW(folder_path);
233 if (!len)
234 lstrcatW(folder_path, L"\\");
236 return folder_path;
239 static HRESULT WINAPI TaskFolder_DeleteFolder(ITaskFolder *iface, BSTR name, LONG flags)
241 TaskFolder *folder = impl_from_ITaskFolder(iface);
242 WCHAR *folder_path;
243 HRESULT hr;
245 TRACE("%p,%s,%lx\n", iface, debugstr_w(name), flags);
247 if (!name || !*name) return E_ACCESSDENIED;
249 if (flags)
250 FIXME("unsupported flags %lx\n", flags);
252 folder_path = get_full_path(folder->path, name);
253 if (!folder_path) return E_OUTOFMEMORY;
255 hr = SchRpcDelete(folder_path, 0);
256 free(folder_path);
257 return hr;
260 static HRESULT WINAPI TaskFolder_GetTask(ITaskFolder *iface, BSTR name, IRegisteredTask **task)
262 TaskFolder *folder = impl_from_ITaskFolder(iface);
263 ITaskDefinition *taskdef;
264 HRESULT hr;
266 TRACE("%p,%s,%p\n", iface, debugstr_w(name), task);
268 if (!task) return E_POINTER;
270 hr = TaskDefinition_create(&taskdef);
271 if (hr != S_OK) return hr;
273 hr = RegisteredTask_create(folder->path, name, taskdef, 0, 0, task, FALSE);
274 if (hr != S_OK)
275 ITaskDefinition_Release(taskdef);
276 return hr;
279 static HRESULT WINAPI TaskFolder_GetTasks(ITaskFolder *iface, LONG flags, IRegisteredTaskCollection **tasks)
281 TaskFolder *folder = impl_from_ITaskFolder(iface);
283 TRACE("%p,%lx,%p: stub\n", iface, flags, tasks);
285 if (!tasks) return E_POINTER;
287 return RegisteredTaskCollection_create(folder->path, tasks);
290 static HRESULT WINAPI TaskFolder_DeleteTask(ITaskFolder *iface, BSTR name, LONG flags)
292 TaskFolder *folder = impl_from_ITaskFolder(iface);
293 WCHAR *folder_path;
294 HRESULT hr;
296 TRACE("%p,%s,%lx\n", iface, debugstr_w(name), flags);
298 if (!name || !*name) return E_ACCESSDENIED;
300 if (flags)
301 FIXME("unsupported flags %lx\n", flags);
303 folder_path = get_full_path(folder->path, name);
304 if (!folder_path) return E_OUTOFMEMORY;
306 hr = SchRpcDelete(folder_path, 0);
307 free(folder_path);
308 return hr;
311 static HRESULT WINAPI TaskFolder_RegisterTask(ITaskFolder *iface, BSTR name, BSTR xml, LONG flags,
312 VARIANT user, VARIANT password, TASK_LOGON_TYPE logon,
313 VARIANT sddl, IRegisteredTask **task)
315 TaskFolder *folder = impl_from_ITaskFolder(iface);
316 IRegisteredTask *regtask = NULL;
317 ITaskDefinition *taskdef;
318 HRESULT hr;
320 TRACE("%p,%s,%s,%lx,%s,%s,%d,%s,%p\n", iface, debugstr_w(name), debugstr_w(xml), flags,
321 debugstr_variant(&user), debugstr_variant(&password), logon, debugstr_variant(&sddl), task);
323 if (!xml) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER);
325 if (!task) task = &regtask;
327 hr = TaskDefinition_create(&taskdef);
328 if (hr != S_OK) return hr;
330 hr = ITaskDefinition_put_XmlText(taskdef, xml);
331 if (hr == S_OK)
332 hr = RegisteredTask_create(folder->path, name, taskdef, flags, logon, task, TRUE);
334 if (hr != S_OK)
335 ITaskDefinition_Release(taskdef);
337 if (regtask)
338 IRegisteredTask_Release(regtask);
340 return hr;
343 static HRESULT WINAPI TaskFolder_RegisterTaskDefinition(ITaskFolder *iface, BSTR name, ITaskDefinition *definition, LONG flags,
344 VARIANT user, VARIANT password, TASK_LOGON_TYPE logon,
345 VARIANT sddl, IRegisteredTask **task)
347 TaskFolder *folder = impl_from_ITaskFolder(iface);
348 IRegisteredTask *regtask = NULL;
349 HRESULT hr;
351 FIXME("%p,%s,%p,%lx,%s,%s,%d,%s,%p: stub\n", iface, debugstr_w(name), definition, flags,
352 debugstr_variant(&user), debugstr_variant(&password), logon, debugstr_variant(&sddl), task);
354 if (!is_variant_null(&sddl))
355 FIXME("security descriptor %s is ignored\n", debugstr_variant(&sddl));
357 if (!is_variant_null(&user) || !is_variant_null(&password))
358 FIXME("user/password are ignored\n");
360 if (!task) task = &regtask;
362 ITaskDefinition_AddRef(definition);
363 hr = RegisteredTask_create(folder->path, name, definition, flags, logon, task, TRUE);
364 if (hr != S_OK)
365 ITaskDefinition_Release(definition);
367 if (regtask)
368 IRegisteredTask_Release(regtask);
370 return hr;
373 static HRESULT WINAPI TaskFolder_GetSecurityDescriptor(ITaskFolder *iface, LONG info, BSTR *sddl)
375 FIXME("%p,%lx,%p: stub\n", iface, info, sddl);
376 return E_NOTIMPL;
379 static HRESULT WINAPI TaskFolder_SetSecurityDescriptor(ITaskFolder *iface, BSTR sddl, LONG flags)
381 FIXME("%p,%s,%lx: stub\n", iface, debugstr_w(sddl), flags);
382 return E_NOTIMPL;
385 static const ITaskFolderVtbl TaskFolder_vtbl =
387 TaskFolder_QueryInterface,
388 TaskFolder_AddRef,
389 TaskFolder_Release,
390 TaskFolder_GetTypeInfoCount,
391 TaskFolder_GetTypeInfo,
392 TaskFolder_GetIDsOfNames,
393 TaskFolder_Invoke,
394 TaskFolder_get_Name,
395 TaskFolder_get_Path,
396 TaskFolder_GetFolder,
397 TaskFolder_GetFolders,
398 TaskFolder_CreateFolder,
399 TaskFolder_DeleteFolder,
400 TaskFolder_GetTask,
401 TaskFolder_GetTasks,
402 TaskFolder_DeleteTask,
403 TaskFolder_RegisterTask,
404 TaskFolder_RegisterTaskDefinition,
405 TaskFolder_GetSecurityDescriptor,
406 TaskFolder_SetSecurityDescriptor
409 HRESULT TaskFolder_create(const WCHAR *parent, const WCHAR *path, ITaskFolder **obj, BOOL create)
411 TaskFolder *folder;
412 WCHAR *folder_path;
413 HRESULT hr;
415 if (path)
417 int len = lstrlenW(path);
418 if (len && path[len - 1] == '\\') return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
421 folder_path = get_full_path(parent, path);
422 if (!folder_path) return E_OUTOFMEMORY;
424 if (create)
426 hr = SchRpcCreateFolder(folder_path, NULL, 0);
428 else
430 DWORD start_index, count, i;
431 TASK_NAMES names;
433 start_index = 0;
434 names = NULL;
435 hr = SchRpcEnumFolders(folder_path, 0, &start_index, 0, &count, &names);
436 if (hr == S_OK)
438 for (i = 0; i < count; i++)
439 MIDL_user_free(names[i]);
440 MIDL_user_free(names);
442 else
444 if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
445 hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
449 if (FAILED(hr))
451 free(folder_path);
452 return hr;
455 folder = malloc(sizeof(*folder));
456 if (!folder)
458 free(folder_path);
459 return E_OUTOFMEMORY;
462 folder->ITaskFolder_iface.lpVtbl = &TaskFolder_vtbl;
463 folder->ref = 1;
464 folder->path = folder_path;
465 *obj = &folder->ITaskFolder_iface;
467 TRACE("created %p\n", *obj);
469 return S_OK;